UTF-8에서`cut -c` (`--characters)를 사용할 수 없습니까?


15

이 명령 cut에는 옵션이있는 -c바이트 대신 문자를 처리하는 옵션이 -b있습니다. 그러나 en_US.UTF-8로케일 에서는 작동하지 않는 것 같습니다 .

두 번째 바이트는 두 번째 ASCII 문자를 제공합니다 (UTF-8과 동일하게 인코딩 됨).

$ printf 'ABC' | cut -b 2          
B

UTF-8 로켈에서 세 개의 그리스어 비 ASCII 문자 중 두 번째를 제공하지 않습니다.

$ printf 'αβγ' | cut -b 2         
�

괜찮습니다-두 번째 바이트 입니다.
따라서 두 번째 문자를 대신 살펴 봅니다 .

$ printf 'αβγ' | cut -c 2 
�

깨진 것 같습니다.
일부 실험에서는 범위 3-4에 두 번째 문자가 표시됩니다.

$ printf 'αβγ' | cut -c 3-4
β

그러나 그것은 바이트 3에서 4와 동일합니다.

$ printf 'αβγ' | cut -b 3-4
β

따라서 UTF-8에 대한 -c것 이상은 아닙니다 -b.

로케일 설정이 UTF-8에 적합하지는 않지만, wc예상대로 작동합니다.
옵션 -c( --bytes)을 사용하여 바이트 수를 계산하는 데 자주 사용됩니다 . (혼동 옵션 이름에 유의하십시오.)

$ printf 'αβγ' | wc -c
6

그러나 옵션 -m( --chars)으로 문자를 계산할 수도 있습니다 .

$ printf 'αβγ' | wc -m
3

그래서 내 구성은 괜찮은 것 같지만 뭔가 특별한 점이 cut있습니다.

어쩌면 UTF-8을 전혀 지원하지 않습니까? 그러나 멀티 바이트 문자를 지원하는 것으로 보이지만 그렇지 않으면 -b및 을 지원할 필요가 없습니다 -c.

무슨 일이야? 그리고 왜?


내가 알 수있는 한 로케일 설정은 utf8을 올바르게 찾습니다.

$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE=en_US.UTF-8
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

입력은 바이트 단위입니다.

$ printf 'αβγ' | hd 
00000000  ce b1 ce b2 ce b3                                 |......|
00000006

흥미 롭습니다! -c와 동일한 코드를 사용하고있는 것 같습니다 -b. 소스 코드를 보셨습니까? 어쩌면 -c실제로 의미 하는 힌트를 찾을 수 있습니다 .
michas

답변:


13

어느 cut것을 사용하고 있는지 말하지는 않았지만 GNU long 옵션을 언급 했으므로 그 옵션 --characters이라고 가정합니다. 이 경우 다음에서이 구절을info coreutils 'cut invocation' 참고하십시오 .

‘-c character-list’
‘--characters=character-list’

문자 목록에 나열된 위치의 문자 만 인쇄하려면 선택하십시오. 와 동일-b지금 하지만 국제화가이를 바꿀 것이다.

(강조 추가)

현재 GNU는 cut항상 1 바이트 "문자"로 작동하므로 사용자가 보는 동작이 예상됩니다.


POSIX 에는 -b-c옵션을 모두 지원 해야합니다. 멀티 바이트를 지원하기 때문에 GNU에 추가되지 않았 으며 제대로 작동했지만 POSIX 호환 입력에 오류가 발생하지 않도록했습니다. FreeBSDOS X는 아니지만 다른 구현 에서도 마찬가지 입니다.cut-ccut

이것은의 역사적인 행동 입니다 -c. 멀티 바이트 문자로 작업 할 수 -b있도록 바이트 역할을 대신하기 위해 새로 추가되었습니다 -c. 진전이 빠르지는 않았지만 (이미 10 년이 지났지 만) 몇 년 안에 일관되게 원하는대로 작동 할 것입니다. GNU 는 직교 적이며 전환을 돕기 위해 아직 옵션을 cut 구현하지 않았습니다-n . 이전 스크립트와의 호환성 문제가있을 수 있지만, 그 이유가 무엇인지는 확실하지 않지만 문제가 될 수 있습니다.


1
잘 했어. GNU tr문서에서도 같은 종류의 주석을 찾을 수 있습니다. 그리고 tar내가 잘못 기억하지 않는 한. 큰 프로젝트 인 것 같아요.
mikeserv

유니 코드 프로브에 대한 해결 방법이 cut있습니까? 예를 들어 패치 된 소스를 어디에서 다운로드 할 수 cut있습니까? 아니면 다른 유틸리티를 사용하는 것이 더 쉬울까요? ( grep아래의 솔루션은 예를 들어 범위에서 부드럽게 작동하지 않습니다 5-8,44-49)
dma_k

2017 년 기사, “GNU Coreutils에서 멀티 바이트 및 유니 코드 지원을 추가하기위한 지속적인 노력에 관한 랜덤 노트 및 포인터”참조 : crashcourse.housegordon.org/coreutils-multibyte-support.html
myrdd December

당신은 몇 가지 대안을 찾을 수 있습니다 cut -c: 여기 superuser.com/questions/506164/...
myrdd

5

colrm(의 일부는 util-linux이미 대부분의 배포판에 설치되어 있어야 함) 국제화를 훨씬 잘 처리하는 것으로 보입니다.

$ echo 'αβγ' | colrm 3
αβ
$ echo 'αβγ' | colrm 2
α

번호 매기기주의 : colrm N에서 열을 제거합니다N 하고 최대 문자를 인쇄합니다 N-1.

( 크레딧 )


2

많은 grep구현이 멀티 바이트를 인식하므로을 사용 grep -o하여 일부 사용 을 시뮬레이션 할 수도 있습니다 cut -c.

$ echo Τηεοδ29 | grep -o '^..'
Τη
$ echo Τηεοδ29 | egrep -o '^..' | grep -o '.$'
η

cut범위 를 시뮬레이트 할 기간 수를 조정하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.