一連のUnicode文字を見つけるためにgrepを使用する方法は?
キャラクターの例を見ました。Unicode値で文字をgrepする方法は?
シェルの交換方法以外の方法に興味があります。
シェルの交換は少し制限的なように見えるため、たとえば\u80コードポイントなどのグラフィックスではなくUnicode文字では機能しないようです。
この方法を特定の範囲内で動作させることができますが、\u80(Unicodeコードポイント80)などの非グラフィック文字を含まない点までのみ可能です。
$ echo grep [$'\u41'-$'\u45']
grep [A-E]
$ echo 4142434445|xxd -r -p
ABCDE
$ echo 4142434445|xxd -r -p | grep [$'\u41'-$'\u45']
ABCDE
$メソッドはシェルレベルで置換を使用するため、たとえば文字を見つけるのには機能しません\u0080-\uFFFF
。\u0080
これは、シェルが文字を表示できないと機能しないためです。
ugrep は Debian の apt-get を通して利用できますが、VPS の私の Ubuntu バージョンでは動作しません。もう一度テストしてみてください。
ノート シェルの置き換え方法は制御文字に対して機能するため、さまざまな制御文字やUnicode文字、そして間違いなくugrepもうまく機能します。最初にシェル置換のためにgrepを使用しようとしたとき、私は知らない間違ったバイトを入力しました。例echo 418042| xxd -r -p
が示されており、A▒B
これがうまくいくと思い、grepを試しています。だからgrepに間違ったデータを渡しています。 80は\u80のutf-8ではありません。高いビット文字(£)などのエコーは、UTF-8を出力していることを明確に示します。 £をecho £ | xxd -p
表示するc2a3はc2a30a
utf-8です。正しいバイトを入力すると機能します。たとえば、c280
\u80も echo $'\u80'
機能します。このページは、utf-8とUnicodeコードポイントのマッピングを示すのに適しています。https://www.utf8-chartable.de/
シェル置換が機能している間にシェル置換以外の操作を実行する回答があることを嬉しく思います。代替案があれば良いだろうからです。
答え1
gnu-grepと同様のエントリではPCREオプションを使用し、次の-P
構文
\x{HHHH}
を使用できます。
$ grep -o -P '[\x{0410}-\x{042F}]+' # same as: grep -o -P '[А-Я]+'
абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕ
=> АБВГДЕ
答え2
GNUシステムでは、少なくとも文字がマルチバイト(UTF-8、GB18030など)にマップされるロケールのUnicodeコードポイントとは異なる方法のバイト値(ASCIIまたはISOを使用するロケール)に基づく順序を保証する必要がありLC_COLLATE
ますC
。 8859-1は、Unicodeコードポイントの順序とも一致する必要があります。
だから:
LC_COLLATE=C grep $'[\u1111-\uaaaa]'
U + 1111とU + AAAAの間にUnicodeコードポイントを持つ1つ以上の文字を含む行を見つける必要があります(設定に示されているロケールの文字マップに従ってエンコードされていますLC_CTYPE
)。他に設定されたものがないと仮定します$LC_ALL
(より優先するので$LC_COLLATE
)。
間違ったU+D800 - U+DFFFの範囲を超えないことをお勧めします。この範囲のコードポイントはUTF-16エンコーディング用に予約されており、有効な文字には適さず、一部のツールで誤った文字をエンコードするために使用されました。 U+0001、U+D7FF、U+E000、U+10FFFF 内の文字を使用してください。
また、範囲の境界がロケールの有効な文字と一致することを確認する必要があります。$'\uxxxx'
(U+xxxx はロケール文字セットの文字ではない) の動作は、$'\u...'
この演算子をサポートするシェルによって異なります。一部のシェル(zshのksh93を含む$'...'
)$'\u...'
は$'\u...'
、UTF-8を文字マップとして使用するロケールでのみ機能します(出力を参照locale charmap
)。
答え3
私はいくつかのPerlの専門家にインタビューしました。そして、一連のUnicode文字を見つけるためにgrepと同等のperl onelinerを得ました。
$ echo £
£
そのため、文字を数字で表現した序数という概念があります。 (何がエンコードかコードポイントかを推測します。序数という単語はオプションによってエンコーディングになる可能性があるため、\x の後の内容を説明するのに便利です。なし(保存/メモリへの書き込み用)
バイト/オクテット単位。さまざまなベースで表現できます。
%v
printf の書式指定子です。
$ perl -e 'printf "%vx\n",A'
41
$ perl -e 'printf "%vx\n",4'
34
%vdは52(文字「4」の10進表現)です。 %vxは16進表現です。
£のUTF-8エンコーディングはc2a3です。 https://www.utf8-chartable.de/
$ echo £ | xxd -p
c2a30a
2 桁以上の \x を使用する場合は、中かっこを使用する必要があります。 \X{..}
$ echo £ | perl -CIO -ne 'print if /[\x0A]/'
£
$ echo £ | perl -CIO -ne 'print if /[\x{0080}-\x{FFFF}]/'
£
-CIO UTF-8表現(c2a3)の序数をUnicodeコードポイント表現(a3)に変換します。したがって、\x で -CIO を使用する場合、\x の後に続く内容は Unicode コードポイント表現でなければなりません。
以下は\u0080以上の項目と一致します。 \uFFFF で停止しません。ただ正規表現です。
$ echo £ | perl -CIO -ne 'print if /[^\x00-\x7f]/'
£
-CIOを削除すると、UnicodeコードポイントバイトではなくUTF-8バイトと一致します。 -CIがなければ、UTF-8でエンコードされたバイトをUnicodeコードポイントに変換/解釈/デコードしません。
$ echo £ | perl -ne 'print if /\xc2/'
£
$ echo £ | perl -ne 'print if /\xa3/'
£
だから要約すると
$ echo £ | perl -CIO -ne 'print if /[\x{0080}-\x{FFFF}]/'
£
$ echo £ | perl -CIO -ne 'print if /[^\x00-\x7f]/'
£
$ echo £ | perl -CIO -ne 'print if /[^\x{00}-\{x7f}]/'
£
$ echo £ | perl -CIO -ne 'print if /[^\x{0000}-\{x007f}]/'
£
perl -CIO
次から録音perldoc perlrun
-C [*number/list*]
The -C flag controls some of the Perl Unicode features.
...
I 1 STDIN is assumed to be in UTF-8
O 2 STDOUT will be in UTF-8
そしてperldoc perlunicodeとperldoc perlreが言及されました\x{...}