이 명령에는 옵션을 사용하여 바이트 대신 문자를 처리하는 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
답변1
당신은 어떤 것을 사용하고 있는지 말하지 않았지만 cut
GNU 긴 옵션을 언급했으므로 --characters
나는 그것이 그 옵션이라고 가정하겠습니다. 이런 경우에는 주의하세요단락의 내용info coreutils 'cut invocation'
:
‘-c character-list’ ‘--characters=character-list’
문자 목록에 나열된 위치의 문자만 인쇄하려면 선택하세요.
-b
지금과 똑같아, 그러나 국제화로 인해 상황이 바뀔 것입니다.
(강조 추가)
현재 GNU는 cut
항상 단일 바이트 "문자" 측면에서 작동하므로 예상되는 동작이 표시됩니다.
지원 -b
과 -c
옵션 모두POSIX 요구 사항cut
— 멀티바이트를 지원하고 제대로 작동하기 때문에 GNU에 추가되지 않았지만 POSIX 호환 입력에서 오류를 방지하기 위한 것입니다. -c
다른 구현에서도 동일한 작업이 수행됩니다 cut
.FreeBSD'모래운영 체제적어도 그렇습니다.
이것은역사적 행동의 -c
. -b
새로운 추가 사항은 -c
멀티바이트 문자를 처리할 수 있도록 바이트 역할을 대신하는 것입니다. 아마도 몇 년 후에는 항상 예상대로 작동할 것입니다. 물론 진행 속도가 그다지 빠르지는 않지만(10년이 넘었습니다). 암소 비슷한 일종의 영양cut
-n
옵션이 구현되지도 않았습니다.그러나 직교하고 전환을 돕기 위해 설계되었습니다. 원인이 무엇인지는 확실하지 않지만 이전 스크립트에는 잠재적인 호환성 문제가 있어 문제가 될 수 있습니다.
답변2
colrm
util-linux
( 대부분의 배포판에 이미 설치되어 있는 의 일부 )은 국제화를 더 잘 처리하는 것 같습니다.
$ echo 'αβγ' | colrm 3
αβ
$ echo 'αβγ' | colrm 2
α
번호 매기기에 유의하세요. 인쇄된 문자까지 colrm N
열이 제거됩니다 .N
N-1
(신용 거래)
답변3
많은 구현이 멀티바이트를 인식하므로 이를 grep
사용하여 .grep -o
cut -c
처음 두 문자:
$ echo Τηεοδ29 | grep -o '^..'
Τη
마지막 세 문자:
$ echo Τηεοδ29 | grep -o '...$'
δ29
두 번째 문자:
$ echo Τηεοδ29 | grep -o '^..' | grep -o '.$'
η
기간 수를 조정하거나 {x,y}
구문을 사용하여 범위를 시뮬레이션합니다 cut
.
답변4
8년이 넘도록 OP의 문제를 재현할 수 없습니다(MacOS 13.4 Ventura).
~$ printf 'ABC' | cut -b 2
B
~$ printf 'αβγ' | cut -b 2
�
~$ printf 'αβγ' | cut -c 2
β
~$ printf 'αβγ' | cut -c 3-4
γ
~$ printf 'αβγ' | cut -b 3-4
β
~$ printf 'αβγ' | wc -c
6
~$ printf 'αβγ' | wc -m
3
위의 내용이 OP가 바라는 답변인 것 같나요? 줄의 끝은 cut -c 3-4
실제로 γ%
아래로 반환되어 zsh
부분 줄(반환될 수 있는 것보다 더 많은 문자가 요청됨)을 나타냅니다.
-$ man cut
사양에 대한 확장으로 macOS 13.4 August 3, 2017
추가 플래그가 있는 IEEE Std 1003.2-1992("POSIX.2") 이외의 버전은 제공되지 않습니다 .-w
"역사: cut 명령은 AT&T System III UNIX에 나타납니다."