파일(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
소문자입니다 .)L
1
또는:
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