tr이 ASCII가 아닌(유니코드) 문자를 인식하도록 만드는 방법은 무엇입니까?

tr이 ASCII가 아닌(유니코드) 문자를 인식하도록 만드는 방법은 무엇입니까?

파일(UTF-8)에서 일부 문자를 제거하려고 합니다. tr이 목적 으로 내가 사용하는 것 :

tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat 

파일에 일부 외국 문자(예: "Латвийская" 또는 "àé")가 포함되어 있습니다. tr그것들을 이해하지 못하는 것 같습니다: 그것은 그것들을 알파가 아닌 것으로 취급하고 제거합니다.

일부 로케일 설정을 변경해 보았습니다.

LC_CTYPE=C LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=C tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat
LC_CTYPE=ru_RU.UTF-8 LC_COLLATE=ru_RU.UTF-8 tr -cs '[[:alpha:][:space:]]' ' ' <testdata.dat

불행히도 이들 중 어느 것도 작동하지 않습니다.

유니코드를 어떻게 이해할 수 있나요 tr?

답변1

이것은 알려진 (1,2,,4,5,6) GNU 구현의 한계 tr.

지원하지 않는 것은 아니다.외국의, 영어가 아니거나 ASCII가 아닌 문자이지만 멀티바이트 문자는 지원하지 않습니다.

iso8859-5(문자당 1바이트) 문자 세트로 쓰는 경우(로케일이 해당 문자 세트를 사용하는 경우) 이러한 키릴 문자는 올바르게 처리되지만 문제는 ASCII가 아닌 UTF-8 문자를 사용한다는 것입니다. 2바이트 이상으로 인코딩됩니다.

GNU는계획(바라보다반품) 이 문제를 해결하기 위한 작업이 진행 중이지만 아직 구현되지 않았습니다.

FreeBSD나 Solaris에는 tr이 문제가 없습니다.


한편, 대부분의 사용 사례에서는 tr멀티바이트 문자를 지원하는 GNU sed 또는 GNU awk를 사용할 수 있습니다.

예를 들어:

tr -cs '[[:alpha:][:space:]]' ' '

다음과 같이 쓸 수 있습니다:

gsed -E 's/( |[^[:space:][:alpha:]])+/ /'

또는:

gawk -v RS='( |[^[:space:][:alpha:]])+' '{printf "%s", sep $0; sep=" "}'

소문자와 대문자( ) tr '[:upper:]' '[:lower:]'사이를 변환 하려면:

gsed 's/[[:upper:]]/\l&/g'

( 숫자 가 아닌 l소문자입니다 .)L1

또는:

gawk '{print tolower($0)}'

이식성을 위해 perl또 다른 옵션이 있습니다.

perl -Mopen=locale -pe 's/([^[:space:][:alpha:]]| )+/ /g'
perl -Mopen=locale -pe '$_=lc$_'

데이터가 단일 바이트 문자 집합으로 표현될 수 있다는 것을 알고 있으면 해당 문자 집합으로 처리할 수 있습니다.

(export LC_ALL=ru_RU.iso88595
 iconv -f utf-8 |
   tr -cs '[:alpha:][:space:]' ' ' |
   iconv -t utf-8) < Russian-file.utf8

답변2

GNU sed를 사용하세요( LANG예: 적절한 환경 변수 포함 en_US.UTF-8).

% sed 'y/123/abc/; y/āōī/456/' <<< test123ingmāōī
testabcingm456

관련 정보