我在文字檔案中有 Unicode 字元 ᚠ,由其 Unicode 代碼點 16A0 表示(該文字檔案被編碼(?)為 utf-8)。
當我這樣做時,grep '\u16A0' test.txt
我沒有得到任何結果。我如何 grep 該字元?
答案1
答案2
你可以使用烏格勒普作為 grep 的直接替換,以匹配 Unicode 代碼點 U+16A0:
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 停用)。正規表示式模式語法符合 POSIX ERE 標準,並使用類似 PCRE 的語法進行了擴展。選項 -P 也可用於 Perl 與 Unicode 模式的匹配。
看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
ᚠ ᚡ ᚢ ᚣ ᚤ ᚥ ᚦ ᚧ ᚨ ᚩ ᚪ ᚫ ᚬ ᚭ ᚮ ᚯ ᚰ ᚱ ᚲ ᚳ ᚴ ᚵ ᚶ ᚷ ᚸ ᚹ ᚺ ᚻ ᚼ ᚽ ᚾ ᚿ ᛀ ᛁ ᛂ ᛃ ᛄ ᛅ ᛆ ᛇ ᛈ ᛉ ᛊ ᛋ ᛌ ᛍ ᛎ ᛏ ᛐ ᛑ ᛒ ᛓ ᛔ ᛕ ᛖ ᛗ ᛘ ᛙ ᛚ ᛛ ᛜ ᛝ ᛞ ᛟ ᛠ ᛡ ᛢ ᛣ ᛤ ᛥ ᛦ ᛧ ᛨ ᛩ ᛪ ᛫ ᛬ ᛭ ᛮ ᛯ ᛰ
匹配字符,列印(空格分隔的)“word”:
~$ 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
給正規表示式引擎),儘管最新版本的 GNUgrep
至少在使用UTF-8 作為其字元映射的語言環境中呼叫時會自動執行此操作。對於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
use-Mopen=locale
而不是-C
告訴它根據語言環境的字元集而不是 UTF-8 對輸入/輸出進行解碼/編碼:
$ 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 中,您還可以使用$'\u20ac'
which 將擴展為當時當前語言環境中字符的編碼(如果該語言環境中沒有此類字符,則報告錯誤)。
$ echo € | grep -F -- $'\u20ac'
€
其他幾個 shell 也從 zsh 複製了它$'\uHHHH'
,包括ksh93、bash、mksh 和一些基於ash 的shell,但有一些不幸的差異:在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 編碼,因為在 shell 解析LC_CTYPE=en_GB.iso885915
時尚未運行。$'\u20ac'