일련의 유니코드 문자를 찾기 위해 grep을 사용하는 방법은 무엇입니까?

일련의 유니코드 문자를 찾기 위해 grep을 사용하는 방법은 무엇입니까?

일련의 유니코드 문자를 찾기 위해 grep을 사용하는 방법은 무엇입니까?

캐릭터의 예를 봤습니다.유니코드 값으로 문자를 grep하는 방법은 무엇입니까?

쉘 교체 방법 이외의 방법에 관심이 있습니다.

쉘 교체는 약간 제한적인 것처럼 보이기 때문에 예를 들어 \u80 코드 포인트와 같은 그래픽이 아닌 유니코드 문자에서는 작동하지 않는 것 같습니다.

이 방법을 특정 범위 내에서 작동하도록 할 수 있지만 \u80(유니코드 코드 포인트 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은 데비안의 apt-get을 통해 사용할 수 있지만 VPS의 내 우분투 버전에서는 작동하지 않습니다. 다시 테스트 해봐야 겠습니다.

노트 쉘 교체 방법은 제어 문자에 대해 작동하므로 다양한 제어 문자나 유니코드 문자, 그리고 의심할 바 없이 ugrep도 잘 작동할 것입니다. 처음에 쉘 대체를 위해 grep을 사용하려고 시도했을 때 나도 모르게 잘못된 바이트를 입력했습니다. 예제가 echo 418042| xxd -r -p보여서 A▒B이것이 잘 작동한다고 생각하고 grep을 시도하고 있습니다. 그래서 grep에 잘못된 데이터를 전달하고 있습니다. 80은 \u80의 utf-8이 아닙니다. 높은 비트 문자(예: £)의 에코는 UTF-8을 출력하고 있음을 명확하게 나타냅니다. £를 echo £ | xxd -p표시하는 c2a3은 c2a30autf-8입니다. 올바른 바이트를 입력하면 작동합니다. 예를 들어 c280\u80도 echo $'\u80'작동합니다. 이 페이지는 utf-8과 유니코드 코드 포인트의 매핑을 보여주는 데 적합합니다.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)에 매핑되는 로케일의 유니코드 코드 포인트와 다른 방식의 바이트 값(ASCII 또는 ISO를 사용하는 로케일)을 기반으로 한 순서를 보장 LC_COLLATE해야 합니다 C. 8859-1은 유니코드 코드 포인트 순서와도 일치해야 합니다.

그래서:

LC_COLLATE=C grep $'[\u1111-\uaaaa]'

U+1111과 U+AAAA 사이의 유니코드 코드 포인트가 있는 문자가 하나 이상 포함된 행을 찾아야 합니다(설정에 표시된 로캘의 문자 맵에 따라 인코딩됨 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 전문가를 인터뷰했습니다. 그리고 일련의 유니코드 문자를 찾기 위해 grep과 동등한 perl oneliner를 얻었습니다.

$ echo £
£

그래서 문자를 숫자로 표현한 서수라는 개념이 있습니다. (무엇이 인코딩인지 코드 포인트인지 추측합니다. 서수라는 단어는 옵션에 따라 인코딩이 될 수 있으므로 \x 뒤에 오는 내용을 설명하는 데 유용하므로 바이트가 저장되거나 유니코드 코드 포인트가 될 수 있습니다. , 바이트이지만 인코딩되지 않음(저장/메모리에 쓰기용)

바이트/옥텟 단위입니다. 다양한 베이스로 표현될 수 있습니다.

%vprintf의 형식 지정자입니다.

$ 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

두 자리 이상의 \x를 사용하는 경우 중괄호를 사용해야 합니다. \엑스{..}

$ echo £ | perl -CIO -ne 'print if /[\x0A]/'
£

$ echo £ | perl -CIO -ne 'print if /[\x{0080}-\x{FFFF}]/'
£

-CIO UTF-8 표현(c2a3)의 서수를 유니코드 코드 포인트 표현(a3)으로 변환합니다. 따라서 \x와 함께 -CIO를 사용할 때 \x 뒤에 오는 내용은 유니코드 코드 포인트 표현이어야 합니다.

다음은 \u0080 이상의 항목과 일치합니다. \uFFFF에서 멈추지 않습니다. 그냥 정규식입니다.

$ echo £ | perl -CIO -ne 'print if /[^\x00-\x7f]/'
£

-CIO를 제거하면 유니코드 코드 포인트 바이트가 아닌 UTF-8 바이트와 일치합니다. -CI가 없으면 UTF-8로 인코딩된 바이트를 유니코드 코드 포인트로 변환/해석/디코딩하지 않습니다.

$ 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{...}

관련 정보