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


36

파일 (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유니 코드 를 이해하려면 어떻게 해야합니까?

답변:


29

이는 GNU 구현의 알려진 ( 1 , 2 , 3 , 4 , 5 , 6 ) 제한 사항입니다 tr.

이 정도는 지원하지 않는 아니라 외국 , 영어 이외의 언어 또는 비 ASCII 문자를하지만 멀티 바이트 문자를 지원하지 않습니다.

이 키릴 문자는 iso8859-5 (문자 당 1 바이트) 문자 세트 (및 로케일이 해당 문자 세트를 사용하고 있음)로 작성된 경우 OK로 취급되지만 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소문자 인 L아닌 1숫자).

또는:

gawk '{print tolower($0)}'

이식성을 위해 perl또 다른 대안이 있습니다.

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

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

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

1
tr에 대한 정보로 인해 귀하의 질문을 수락했습니다. 문제를 해결하고 해결 방법에 대한 질문을 제거했습니다 (따라서 tr을 찾는 사람들은 임의의 문제가 아니라 tr에 대한 정보 만 찾을 수 있습니다). 더 이상 필요하지 않기 때문에 솔루션을 제거 할 수 있다면 감사하겠습니다.
MatthewRock

3
@ MatthewRock 나는 그것을 유지했지만 단어를 바꾸는 것은 같은 문제를 가진 사람들에게 유용 할 것이므로 더 일반적으로 만들었습니다.
Stéphane Chazelas

키릴 문자가 ISO 8859-5로 (일반적으로) 인코딩된다는 아이디어는 어디서 얻습니까? 유니 코드 이외의 다른 러시아어 텍스트를 본 적이 있습니까?
Incnis Mrsi

9
@IncnisMrsi, 여기서 중요한 것은 ISO 8859-5가 키릴 문자를 가진 1 바이트 문자 세트 중 하나라는 것입니다. 널리 사용되는지 여부는 여기와 관련이 없습니다. KOI-R 또는 window-1251 문자 세트가있는 로케일이있는 경우 반드시 대신 사용하십시오.
Stéphane Chazelas

웹에서 @IncnisMrsi 러시아어는 거의 항상 UTF-8 (또는 때때로 Windows-1251)로 인코딩되지만, 초기에 많은 단일 바이트 인코딩의 고통을 느꼈기 때문입니다. 다음은 (비 기능적) 인코딩 스위처가있는 고대 (1998 년경) 웹 페이지입니다 : sch57.ru/collect .
Alex Shpilkin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.