유니코드 문자의 tr 시뮬레이션?

유니코드 문자의 tr 시뮬레이션?

동일한 작업을 수행하려면 국제화 유틸리티가 필요합니다 tr. 즉, 스트림에서 문자를 가져와 해당 문자로 바꿉니다. 상향식과 같은 특정 사례 솔루션 대신 일반적인 사례 솔루션이 필요합니다. 가능하다면 고릴라 파이프 sed호출은 하지 않습니다.

Linux에서는 작동 tr하지 않습니다. 문자가 아닌 바이트를 변환합니다. 멀티바이트 인코딩에서는 실패합니다.

$ tr --version | head -n 1
tr (GNU coreutils) 8.23
$ echo $LC_CTYPE
en_US.UTF-8
$ echo 'Ångstrom' | tr Æ Œ         
Ņngstrom

답변1

GNU는 sed멀티바이트 문자를 처리합니다. 그래서:

$ echo é½Æ | sed 'y/é½Æ/ABŒ/'
ABŒ

GNU가 아직 국제화되지 않았다는 것이 아니라 tr멀티바이트 문자(예: UTF-8 로케일의 비ASCII 문자)를 지원하지 않는다는 것입니다. GNU는 iso8859-15 문자 집합과 같이 단일 바이트인 한 사용할 tr수 있습니다 .ÆŒ

자세한 내용은 다음을 방문하세요.tr이 ASCII가 아닌(유니코드) 문자를 인식하도록 만드는 방법은 무엇입니까?

어쨌든 이것은 Linux와 관련이 없으며 tr시스템 구현과 관련이 있습니다. 시스템이 Linux를 커널로 사용하는지, Linux용으로 구축되었는지, Linux 커널 API를 사용하는지 tr여부는 중요하지 않습니다. 왜냐하면 이 tr기능 부분은 사용자 공간에서 발생하기 때문입니다.

busybox tr및 GNU 는 Linux용으로 구축된 가장 일반적인 소프트웨어 배포판이며 멀티바이트 문자를 지원하지 않습니다. 그러나 heirloom 도구 상자(OpenSolaris에서 이식됨) 또는 ast-open 도구 상자 tr와 같이 Linux로 이식된 다른 배포판도 있습니다 .tr

는 처럼 지원되지 않습니다 sed. 또한 포함된 스크립트가 UTF-8 문자 세트로 작성된 경우 UTF-8이 아닌 문자 세트가 있는 로케일에서 스크립트를 호출하면 더 이상 예상대로 작동하지 않습니다.ya-zsed 'y/é½Æ/ABŒ/'

또 다른 방법은 다음을 사용하는 것입니다 perl.

perl -Mopen=locale -Mutf8 -pe 'y/a-zé½Æ/A-ZABŒ/'

위에서 Perl 코드는 UTF-8을 기대하지만 로케일 인코딩의 입력을 처리합니다(및 동일한 인코딩의 출력). UTF-8 로케일에서 호출되면 ÆUTF-8(0xc3 0x86)을 UTF-8 Œ(0xc5 0x92)로 음역합니다. 이는 ISO8859-15와 동일하지만 0xc6 -> 0xbc입니다.

대부분의 쉘에서는 UTF-8이 문자 세트가 아닌 로케일에서 스크립트가 호출되더라도 작은따옴표 안에 이러한 UTF-8 문자를 포함하는 것이 좋습니다(예외는 yash바이트가 유효한 문자를 형성하지 않는 경우입니다). 로케일에서 오류가 보고됩니다. 그러나 작은따옴표가 아닌 다른 따옴표를 사용하면 문제가 발생할 수 있습니다. 예를 들어,

perl -Mopen=locale -Mutf8 -pe "y/♣\`/&'/"

(0x5c)의 인코딩이 \일부 다른 문자(예 α: 0xa3 0x5c 및 UTF-8 인코딩이 0xa3으로 끝나기 때문에)에도 포함되기 때문에 문자 세트 BIG5-HKSCS가 있는 로케일에서는 실패합니다.

아무튼 이런 건 기대하지 마세요

perl -Mopen=locale -Mutf8 -pe 'y/Á-Ź/A-Z/'

날카로운 악센트를 제거하기 위해 노력하십시오. 위의 내용은 실제로는

perl -Mopen=locale -Mutf8 -pe 'y/\x{c1}-\x{179}/\x{41}-\x{5a}/'

즉, 범위는 유니코드 코드 포인트를 기반으로 합니다. 따라서 범위는 "" 내에 있는 잘 정의된 시퀀스 외부에서는 쓸모가 없습니다.옳은"유니코드의 순서는 A-Z, 입니다 0-9.

날카로운 악센트를 제거하려면 다음과 같은 고급 도구를 사용해야 합니다.

perl -Mopen=locale -MUnicode::Normalize -pe '
  $_ = NFKD($_); s/\x{301}//g; $_ = NFKC($_)'

즉, 유니코드 정규화된 형식을 사용하여 문자를 분해하고 악센트 표시(여기서는 결합된 형식 U+0301)를 제거한 후 다시 조립합니다.

유니코드를 음역하는 데 유용한 또 다른 도구 uconv는 다음과 같습니다.중환자실. 예를 들어, 위 수식은 다음과 같이 작성할 수도 있습니다.

uconv -x '::NFKD; \u0301>; ::NFKC;'

그러나 UTF-8 데이터에서만 작동합니다. 다음을 수행해야 합니다.

iconv -t utf-8 | uconv -x '::NFKD; \u0301>; ::NFKC;' | iconv -f utf-8

사용자의 로케일에서 데이터를 처리하는 능력.

답변2

Bash에서는 다음을 사용할 수 있습니다.매개변수 확장.

교체 Å성공:

$ string='Hello Ångstrom'
$ a='Å'
$ b='Œ'
$ printf '%s\n' "${string//${a}/${b}}"
Hello Œngstrom

교체해 보세요 Æ. 문자열의 일부가 아닙니다.

$ string='Hello Ångstrom'
$ a='Æ'
$ b='Œ'
$ printf '%s\n' "${string//${a}/${b}}"
Hello Ångstrom

답변3

이것이 인코딩 체계일 수 있습니다. 다음과 같이 iconv를 통해 실행해 보세요.

echo Ångstrom | iconv -f UTF-8 | tr 'Å' 'Œ'

출시사: 옹스트롬

관련 정보