テキスト ファイル内に、Unicode コード ポイント 16A0 で表される Unicode 文字 ᚠ があります (テキスト ファイルは utf-8 としてエンコードされています)。
そうすると、grep '\u16A0' test.txt
結果が返されません。その文字を grep するにはどうすればいいでしょうか?
答え1
使用できますANSI-C 引用符シェルによって提供される を使用し、ANSI C 標準で指定されているバックスラッシュ エスケープ文字を置き換えます。これは、grep
Bash や Zsh などのシェルでは、 だけでなく、任意のコマンドで機能します。
grep $'\u16A0'
より複雑な例については、以下を参照してください。この関連する質問そしてその答え。
答え2
使用できるugrepUnicode コード ポイント U+16A0 に一致する grep の代替として:
ugrep '\x{16A0}' test.txt
grep と同じオプションを取りますが、次のようなはるかに多くの機能を提供します。
ugrepはUTF-8/16/32入力およびその他の形式を検索しますオプション -Q を使用すると、ISO-8859-1 ~ 16、EBCDIC、コード ページ 437、850、858、1250 ~ 1258、MacRoman、KIO8 など、他の多くのファイル形式を検索できます。
ugrepはUnicodeパターンにマッチするデフォルトでは無効です (オプション -U で無効)。正規表現パターン構文は、PCRE のような構文で拡張された POSIX ERE 準拠です。オプション -P は、Unicode パターンとの Perl マッチングにも使用できます。
見るGitHub の ugrep詳細については。
答え3
使用楽(旧称 Perl_6)
サンプル入力:
https://www.cogsci.ed.ac.uk/~richard/unicode-sample-3-2.html
文字を一致させて、行を出力します。
~$ raku -ne '.put if m/ \x[16A0] /;' file
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
#OR:
~$ raku -e 'lines.grep(/ \x[16A0] /).put;' file
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
文字と一致し、(空白で区切られた)「単語」を出力します。
~$ raku -ne 'for .words() { .put if m/ \x[16A0] / };' file
ᚠ
#OR:
~$ raku -e 'words.grep(/ \x[16A0] /).put;' file
ᚠ
文字を一致させ、(正確な)一致を出力します。
~$ raku -e 'given slurp() { put m:g/ \x[16A0] / };' file
ᚠ
#OR:
~$ raku -e 'slurp.match(:global,/ \x[16A0] /).put;' file
ᚠ
文字を一致させ、一致した文字を数えて出力します:
~$ raku -e 'given slurp() { put m:g/ \x[16A0] /.Int };' file
1
#OR:
~$ raku -e 'slurp.match(:global,/ \x[16A0] /).elems.put;' file
1
ノート:
Raku では、 のような Unicode 名と簡単に一致させることができ
\c[RUNIC LETTER FEHU FEOH FE F]
、上記と一致させるのと同じ結果が得られます\x[16A0]
。Raku では、 などの Unicode 文字と簡単に一致させることができ、またはそれ以上
ᚠ
と一致させるのと同じ結果が得られます。\x[16A0]
\c[RUNIC LETTER FEHU FEOH FE F]
Raku では、Unicode 変数 (および Unicode 演算子) を使用できます。つまり、次のように動作します。
~$ raku -e 'my $ᚠ = slurp.match(/ \x[16A0] /); say $ᚠ.Str.raku;' file
"ᚠ"
https://docs.raku.org/language/regexes#Unicode_properties
https://docs.raku.org/language/unicode
https://docs.raku.org
https://raku.org
答え4
perl
、、pcre2grep
または少なくとも PCRE または PCRE2 を使用するか使用できる実装では、 を使用して、pcregrep
値(または値 <= 0xff のみ) を持つ文字に一致させることができます。grep
\x{16A0}
0x16A0
\xe9
その値が Unicode コード ポイントであるためには、入力が UTF-8 からデコードされる必要があることを指示する必要があります。PCRE/PCRE2 では、(*UTF)
パターンの先頭で を使用します (PCRE_UTF
正規表現エンジンに渡すこととほぼ同じ)。ただし、GNU の最近のバージョンgrep
では、少なくとも UTF-8 を charmap として使用するロケールで呼び出されたときには自動的に実行されます。 および ではpcregrep
、オプションを使用しpcre2grep
てこれを有効にすることもできます-u
( の も参照-U
) pcre2grep
。
ではperl
、これは環境変数-C
の (big char) オプションを介して行われますPERL_UNICODE
。-C
単独では、 の短縮形は、-CSDL
ロケールが GNU のように UTF-8 を使用する場合に入力/出力を UTF-8 としてデコード/再コードします。grep
または、-CSD
を使用すると無条件にデコードしたり、たとえば モジュールを使用して任意のエンコーディングから明示的にデコードしたりできますEncode
。
および PCRE2 (または GNU の最新バージョンperl
で使用されている)では、 も使用できます。また、その Unicode 名では です。pcre2grep
grep
\N{U+16A0}
perl
\N{RUNIC LETTER FEHU FEOH FE F}
それで:
perl -C -ne 'print if /\x{16A0}/'
perl -C -ne 'print if /\N{U+16A0}/'
perl -C -ne 'print if /\N{RUNIC LETTER FEHU FEOH FE F}/'
PERL_UNICODE=SD perl -ne 'print if /\x{16A0}/'
pcregrep -u '\x{16A0}'
pcregrep '(*UTF)\x{16A0}'
pcre2grep -u '\x{16A0}'
pcre2grep '(*UTF)\x{16A0}'
pcre2grep -U '\x{16A0}'
pcre2grep -u '\N{U+16A0}'
grep -P '\x{16A0}'
UTF-8 でエンコードされていない入力で Unicode 値に基づいて文字を一致させる場合、これらは UTF-8 でのみ機能するため機能しません。 シングルバイト文字セットでは、は\xHH
値 (Unicode ではなく、対応する文字セットのコードポイント) によって機能します。
たとえばen_GB.iso885915
、ユーロ記号 (U+20AC) が 0xA4 にあるロケールの場合。
$ LC_ALL=en_GB.iso885915 luit
$ locale charmap
ISO-8859-15
$ printf %s € | od -An -vtx1
a4
$ echo € | grep -P '\x{20ac}'
grep: character code point value in \x{} or \o{} is too large
$ echo € | grep -P '\N{U+20ac}'
grep: \N{U+dddd} is supported only in Unicode (UTF) mode
$ echo € | grep -P '(*UTF)\N{U+20ac}'
$ echo € | grep -P '\xA4'
€
したがって、テキストを UTF-8 に変換するオプションは次のようになります。
$ echo € | iconv -t utf-8 | LC_ALL=C.UTF-8 grep -P '\x{20ac}' | iconv -f utf-8
€
または、の代わりにperl
を使用する場合は、UTF-8 ではなくロケールの文字セットに従って入力/出力をデコード/エンコードするように指示します。-Mopen=locale
-C
$ echo € | perl -Mopen=locale -ne 'print if /\N{U+20ac}/'
€
または、デコードを行わず、ロケール内のその文字のバイト値に一致させます。
たとえば、GNU や zsh、または最近のバージョンの bash の場合printf
:
$ locale charmap
ISO-8859-15
$ printf '\u20ac' | od -An -vtx1
a4
$ echo € | grep -F -- "$(printf '\u20ac')"
€
zsh では、その時点の現在のロケールの文字のエンコーディングに展開する which を使用することもできます$'\u20ac'
(そのロケールにそのような文字が存在しない場合はエラーを報告します)。
$ echo € | grep -F -- $'\u20ac'
€
それ以来、ksh93、bash、mksh、およびいくつかのashベースのシェルを含むいくつかの他のシェルが$'\uHHHH'
zshからこれをコピーしてきましたが、残念なことにいくつかの違いがあります。kshでは、ロケールに関係なくUTF-8で展開されますが、bashでは、コードの実行時ではなく、コードが読み取られた時点でのロケールで展開されます。たとえば、次のようになりますbash
。
LC_CTYPE=C.UTF-8
{
LC_CTYPE=en_GB.iso885915
printf '\xA4\n' | grep -F -- $'\u20ac'
}
または:
LC_CTYPE=C.UTF-8
euro() {
grep -F -- $'\u20ac'
}
LC_CTYPE=en_GB.iso885915
printf '\xa4\n' | euro
どちらの場合も、がシェルによって解析された時点では が実行されていなかった$'\u20ac'
ため、 は UTF-8 エンコーディングに展開されるため、動作しません。LC_CTYPE=en_GB.iso885915
$'\u20ac'