유니코드 값으로 문자를 grep하는 방법은 무엇입니까?

유니코드 값으로 문자를 grep하는 방법은 무엇입니까?

유니코드 코드 포인트 16A0으로 표시되는 텍스트 파일에 유니코드 문자 ᚠ가 있습니다(텍스트 파일은 utf-8로 인코딩(?)됩니다).

이렇게 하면 grep '\u16A0' test.txt결과가 나오지 않습니다. 이 캐릭터를 어떻게 찾을 수 있나요?

답변1

당신은 그것을 사용할 수 있습니다ANSI-C 인용문ANSI C 표준에 지정된 백슬래시 이스케이프 문자를 대체하기 위해 셸에서 제공됩니다. 이는 grepBash 및 Zsh와 같은 셸의 명령 뿐만 아니라 모든 명령에서 작동합니다 .

grep $'\u16A0'

좀 더 복잡한 예를 보려면 다음을 참조하세요.이 관련 질문그리고 그 대답.

답변2

당신이 사용할 수있는우그레프유니코드 코드 포인트 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은 유니코드 패턴과 일치합니다.기본적으로(-U 옵션으로 비활성화됨) 정규식 패턴 구문은 POSIX ERE 표준을 따르며 PCRE와 유사한 구문으로 확장됩니다. -P 옵션은 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 

노트:

  1. Raku에서는 유니코드 이름을 쉽게 일치시킬 수 있습니다 \c[RUNIC LETTER FEHU FEOH FE F]. 예를 들어 위의 일치와 동일한 결과를 제공합니다 \x[16A0].

  2. Raku에서는 예를 들어 유니코드 문자를 쉽게 일치시킬 수 있으며, 이는 일치 이상과 동일한 결과를 제공합니다.\x[16A0]\c[RUNIC LETTER FEHU FEOH FE F]

  3. Raku에서는 유니코드 변수(및 유니코드 연산자)를 사용할 수 있습니다. 그래서 이것은 작동합니다 :

~$ raku -e 'my $ᚠ = slurp.match(/  \x[16A0]  /); say $ᚠ.Str.raku;'   file
"ᚠ"

https://docs.raku.org/언어/regexes#Unicode_properties
https://docs.raku.org/언어/unicode
https://docs.raku.org
https://raku.org

답변4

을 사용 perl하거나 pcre2grep적어도 pcregrepPCRE 또는 PCRE2 구현을 사용하면 문자를 값과 일치시키는 데 사용할 수 있습니다(또는 값 ​​<= 0xff에 대해서만).grep\x{16A0}0x16A0\xe9

값이 유니코드 코드 포인트가 되려면 입력이 UTF-8에서 디코딩되어야 한다고 알려야 합니다. PCRE/PCRE2에서는 (*UTF)패턴의 시작 부분에서 이를 사용하여 수행됩니다 (주로 PCRE_UTF정규식 엔진에 전달하는 것과 동일). 그러나 최신 버전의 GNU는 grep최소한 UTF-8을 사용하는 로케일에서 호출될 때 자동으로 이 작업을 수행합니다. 문자 맵 이 작업입니다. pcregrep및 의 경우 pcre2grep옵션을 사용하여 이 기능을 활성화할 수도 있습니다 -u( 참조 -U) pcre2grep.

에서는 환경 변수 의 (큰 문자) 옵션을 perl통해 이루어집니다 . 단독으로 사용하는 경우 약어는 로케일 이 GNU와 같이 UTF-8을 사용하는 경우 입력/출력을 UTF-8로 다시 인코딩하기 위해 디코딩/재인코딩 되거나 이를 무조건 수행하거나 모듈 등을 사용하여 모든 인코딩에서 명시적으로 디코딩합니다 .-CPERL_UNICODE-C-CSDLgrep-CSDEncode

PCRE2(GNU 또는 최신 버전에서 사용 perl)에서는 유니코드 이름이 .pcre2grepgrep\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로 인코딩되지 않은 입력에서 유니코드 값을 기반으로 문자를 일치시키려면 이러한 문자는 UTF-8에서만 작동하므로 작동하지 않습니다. 단일 바이트 문자 집합에서는 \xHH값(유니코드의 코드 포인트가 아닌 해당 문자 집합의 코드 포인트)으로 작동합니다.

예를 들어, 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

또는 대신 perluse를 사용하는 경우 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'

$'\uHHHH'ksh93, bash, mksh 및 일부 ash 기반 쉘을 포함하여 여러 다른 쉘이 이를 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'

관련 정보