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

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

ファイル内のすべての文字を識別してみてください。

ファイルには以下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文字(たとえば、、ɔおよびə)も取得されます。ɪ

ちなみに、使用結果は「\n」行を追加する点を除けばsed 's/\(.\)/\1\n/g'ほぼ同じです。grep -o .

私が逃したものはありますか? grepには隠されたUTF-8オプションがありますか?

重要な場合Ubuntu 12.04.2 LTS

答え1

問題は、ロケールの照合情報にsortあり、それを使用することです。uniq両方のコマンドに対してロケールをオフにすることは有効です。

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 ə

答え2

ただし、「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=./someplaceLC_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> レベルは、行をソートするために使用されるレベルです。

私の考えには(やってはいませんが練習として残しました:)) 最後のレベルだけを定義すればソートするときはほとんど無視されますが、ユニークな観点ではまだ「違う」(チェーンがすべてのレベルはユニークでキャラクターも同じだと思います。)

通常、最初のレベルは、eなどのすべての文字と同じグループ化記号です。 2番目のレベルは通常基本文字に使用され、さまざまなアクセントバージョンと(特別?)「特殊」文字に使用されるさまざまな記号と組み合わせて使用​​されます。 3Dレベルは、大文字と小文字を区別するためによく使用されます。

関連情報