web-dev-qa-db-ja.com

一部のUTF-8文字がgrepまたはsedで認識されない

ファイル内のすべての文字を判別しようとしています。

ファイルsampleは次のもので構成されています。

_a eɪ
abandon əˈbændən
ability əˈbɪləti
able ˈeɪbəl
able ˈeɪbl
abortion əˈbɔrʃən
abortion əˈbɔrʃn
about əˈbaʊt
above əˈbʌv
abroad əˈbrɔd
_

確認されたロケールが正しい:

_$ echo $LANG

en_US.UTF-8
_

2番目のフィールドを文字で分割し、その数を数えるコマンド:

_$ cat sample | awk '{print $2}' | grep -o . | sort | uniq -c | sort -n

  1 a
  1 æ
  1 i
  1 v
  2 d
  2 t
  3 e
  3 l
  3 ɔ
  3 r
  4 n
  9 b
 11 ə
 17 ɪ
_

_ʃ_と_ˈ_はどこにありますか?彼らはキャラクターや特別なものを組み合わせていません。他のUTF-8文字が引き出されていることに注意してください。たとえば、_ɔ_、_ə_、_ɪ_などです。

ところでsed 's/\(.\)/\1\n/g'を使用すると、「\ n」の行が追加されることを除いて、_grep -o ._とほぼ同じ結果になります。

行方不明のものはありますか? grepには隠しUTF-8オプションがありますか?

重要な場合は、_Ubuntu 12.04.2 LTS_を使用しています。

6
Yimin Rong

問題は、sortuniqがロケールの照合情報を使用していることです。 2つのコマンドのロケールをオフに切り替えても機能します。

cat sample | awk '{print $2}' | grep -o . | LC_ALL=C sort | LC_ALL=C uniq -c | sort -n
      1 ʊ
      1 ʌ
      1 a
      1 æ
      1 i
      1 v
      2 ʃ
      2 d
      2 t
      3 e
      3 l
      3 ɔ
      3 r
      4 ɪ
      4 n
      9 ˈ
      9 b
     11 ə
3
choroba

ただし、「C」ロケールを使用すると、人間の照合が失われます(「a」と「A」を同等にするなど)。

照合とglibcロケールデータで処理されない一部の文字の処理の両方が必要な場合。デフォルトの照合を拡張することにより、独自のロケールを作成できます。

現在のロケール(例:/ usr/share/i18n/locales/en_US)の定義を別の名前にコピーできます。次にそれを編集し、LC_COLLATEセクションで次のようにします。

LC_COLLATE
copy "iso14651_t1"

reorder-after <e>
<U0259> <e>;<PCL>;<MIN>;IGNORE
reorder-after <s>
<U0283> <s>;<PCL>;<MIN>;IGNORE
reorder-end

END LC_COLLATE

それをコンパイルします:localedef -f ./yourmodifiedfile -t UTF-8 ./someplaceその後、LC_ALL=./someplace の代わりに LC_ALL=C

定期的に使用したい場合は、作成したディレクトリに他の標準ロケール(通常は/ usr/share/localeまたは/ usr/lib/locale)を付け、標準的な方法で名前を付けます(たとえば、en_USに基づいている場合)たとえば、「en_US @ IPA」という名前を付けることができます。次に、ロケールを設定して、LC_COLLATE = en_US @ IPAを永続的に設定できます(一部のLC_ *変数を個別に定義する場合は、LC_ALLを定義しないでください)。

また、U + 02C8は修飾子であるため、照合では無視してください。ただし、別の文字として処理する必要がある場合は、代わりに使用できます(ASCIIの単一引用符はU + 02C8と同じ(コレートビューの場合)と同じように入力されるため、次のように入力します)。

# defines a handy symbol, to group together similar chars
collating-symbol <'>

# define 
reorder-after <z>
<'>

reorder-after <e>
<U0259> <e>;<PCL>;<MIN>;IGNORE
reorder-after <s>
<U0283> <s>;<PCL>;<MIN>;IGNORE
reorder-after <'>
<U0027> <'>;<BAS>;IGNORE;IGNORE
<U02C8> <'>;<PCL>;IGNORE;IGNORE

reorder-end

行は:<unicode value> <1st level>;<2d level>;<3d level>;<4th level>レベルは、それらをソートするために使用されるものです。

最後のレベルを定義するだけで、ソートではほとんど無視されるように動作しますが、Uniqの観点からは「異なる」と見なされます(ただし、試してみませんでした:)すべてのレベルのユニークなキャラクターがユニークだと思います)。

通常、第1レベルは、すべてのeのような文字と同様に、グループ化記号です。通常、2番目のレベルはベースキャラクター用で、さまざまなアクセント付きバージョン用にいくつかの他の記号があり、(特殊?)は「特別」に使用されます。 3Dレベルは通常、大文字と小文字を区別するために使用されます。

2
Pablo Saratxaga