Bourne 쉘과 호환되는 "${#string}"에서 문자열의 "길이"는 얼마입니까?

Bourne 쉘과 호환되는 "${#string}"에서 문자열의 "길이"는 얼마입니까?

~에서이것논의하다:

내가 (zsh 5.8, bash 5.1.0)

var="ASCII"
echo "${var} has the length ${#var}, and is $(printf "%s" "$var"| wc -c) bytes long"

대답은 간단합니다. 5자이고 5바이트를 차지합니다.

이제 var=Müller출력은

Müller has the length 6, and is 7 bytes long

이는 ${#}연산자가 바이트가 아닌 코드 포인트를 계산한다는 것을 나타냅니다. 이건 좀 불분명해요POSIX에서는, 그들은 "문자"를 계산한다고 말합니다. char일반적으로 POSIX C의 문자가 옥텟이 아닌 경우 이는 더 명확합니다.

어쨌든: 나쁘지 않아요! 다행히 나는 그것을 보았다 LANG==en_US.utf8.

지금,

var='

답변1

POSIX 호환 셸(Bourne 셸이 아님, 기능은 Korn 셸에서 제공됨)에서 계산 ${#var}과 같습니다 .wc -m수치¹ in이고 $var에 저장된 바이트 시퀀스를 $var현재 로케일의 문자로 디코딩할 수 없는 경우 동작은 지정되지 않습니다.

현재 로캘(해당 범주)에 따라 LC_CTYPE바이트를 문자로 디코딩합니다 . 문자 인코딩으로 UTF-8을 사용하는 로케일에서는 0xc3 0xa9 시퀀스가 ​​문자로 디코딩되고, ISO8859-1을 사용하는 로케일에서는 시퀀스가 é​​.é

어쨌든 유니코드 코드 포인트와는 거의 관련이 없습니다. 또한 터미널이나 다른 디스플레이 장치에 표시될 때 문자소 클러스터의 수나 문자열 너비를 계산하는 것과도 다릅니다.

존재하다:

var="e\xcc\x81"

$vare, \, x, c, c, \, x및 9바이트와 9개의 문자를 포함 8합니다 1.

일부 printf(format 매개변수 또는 %bformat 지시문의 매개변수) 및 echo구현은 0xcc 바이트로 확장되지만 \xcc전부는 아닙니다. POSIX에서 \x이러한 논쟁은 지정되지 않은 동작을 초래합니다. ( 형식 매개변수 및 / 에서 \3510xe9 바이트로 확장 됩니다).printf\0351echo%b

//(요즘에는 점점 더 많은 쉘)에 , , 바이트를 $var포함시키 려면 다음과 같이 하십시오.0x650xcc0x81ksh93zshbash

var=$'e\xcc\x81'

아니면 언제든지 다음과 같이 할 수 있습니다.

var=$(printf 'e\314\201')

locale charmap그러면 출력 로케일에는 3바이트( 와 같이 ), 2개의 문자( 또는 와 같이 ), 1개의 자소 클러스터( GNU 에서와 같이 )가 UTF-8포함 되며 일반적으로 너비가 1( 표시된 GNU 에서와 같이 )로 표시됩니다.$varwc -cwc -m${#var}grep -Po '\X'wc -L

쉘이 호출되고 코드가 구문 분석되고 실행될 때 로케일이 문자 세트로 UTF-8을 갖는 경우 여러 쉘에서 다음을 수행할 수도 있습니다.

var=$'e\u0301'

및 U+0301(급 악센트 결합)을 포함하는 문자에 대한 $varUTF-8 인코딩입니다 .e

로케일의 문자 세트가 UTF-8이 아닌 경우 동작은 쉘마다 다릅니다. 또한, 셸에 따라 유니코드 코드 포인트를 문자로 확장할 때 코드를 구문 분석할 때 적용되는 로캘을 고려하는지 아니면 코드를 실행할 때 적용되는 로캘을 고려하는지를 고려합니다. 해당 지역의 참 맵에 캐릭터가 존재하지 않는 경우에도 동작의 변화를 확인할 수 있습니다.

Bourne 쉘에서 문자열의 문자 길이를 얻으려면 다음과 같은 다른 유틸리티를 사용해야 합니다.

length=`expr "x$var" : '.*' - 1` || :

또는:

length=`printf %s "$var" | wc -m`

그러나 여전히 Bourne 쉘이 있는 오래된 시스템을 발견하면 해당 시스템이 명령을 wc지원하지 않거나 -m포함하지 않을 가능성이 있습니다.printf


1 POSIX 자체는 바이트 시퀀스와 문자 시퀀스 간의 매핑을 지정하지 않으며 POSIX 로케일에서도 일부 API만 매핑을 정의 및 검색하거나 바이트 시퀀스를 문자 시퀀스로 변환하는 데 사용됩니다( wchar_t). 시스템은 일반적으로 다른 ISO 표준(ISO/IEC 10646, 일명 유니코드)에서 정의한 문자 세트 변환 형식인 UTF-8과 같은 문자 세트 표준 문자 세트를 사용합니다. GNU 시스템과 같은 일부 시스템은 실제로 wchar_t로케일에 관계없이 유니코드 코드 포인트를 값으로 사용합니다.

관련 정보