예를 들어, 배열을 만든다면:
$ array1=($(find /etc -mindepth 1 -maxdepth 1 -type d))
$ echo ${#array[@]}
105
$ for each in ${array1[@]}; do echo $each ; done
/etc/alternatives
/etc/apache2
/etc/apparmor
/etc/apparmor.d
... so on and so forth, you get the idea.
bash를 사용하여 길이가 아닌 바이트 단위로 크기를 인쇄하는 방법이 있습니까? 아니면 문자 수에 따라 수동으로 계산해야 합니까?
나는 다음과 같은 것을 시도했습니다 :
$ var2="a"
$ echo $var2 | wc -c
2
$ echo $var2
a
하지만 다음은 이렇습니다.
$ var2=""
$ echo $var2 | wc -c
1
$ echo $var2
공백변수의 존재는 1바이트인 것으로 보입니다. 하지만 1글자의 글자수는 2글자입니다.
$ echo a | wc -c
2
$ echo a | wc -m
2
$ echo aa | wc -c
3
$ echo aa | wc -m
3
개행 문자는 1바이트이고 각 문자도 1바이트인 것처럼 보입니다. 배열을 얻고, 새 줄 수를 세고, 문자 수를 세고, 계산을 하는 것은 어려운 것 같습니다. 제가 너무 생각하고 있는 건가요? 아니면 정확한 수치를 알려줄 수 있는 유틸리티가 있나요?
답변1
array1=($(find /etc -mindepth 1 -maxdepth 1 -type d))
find
이는 목록을 얻기 위해 출력에 대해 분할+글로브를 수행하기 때문에 잘못된 것입니다 (어쨌든 find
없는 출력은 -print0
사후 처리가 불가능합니다). (4.4+)의 올바른 구문은 bash
다음과 같습니다.
readarray -td '' array1 < <(find /etc -mindepth 1 -maxdepth 1 -type d -print0)
또는 zsh
:
array1=(/etc/*(ND/))
존재하다echo $var | wc -c
출력에서 바이트를 계산하고 있습니다 echo
. $var
이는 여러 가지 이유로 바이트 수가 아닙니다.
- 인용하는 것을 잊었
$var
으므로 분할+글로브의 영향을 받습니다. echo
전환을 해보세요. 일부 구현은\x
이스케이프 시퀀스를 확장하고 일부는 값을-n
옵션 으로 취급합니다.- 마지막으로
echo
개행 문자가 출력에 추가됩니다(-n
일부 구현에서는 건너뛸 수 있음echo
).
여기서 wc
바이트 수를 계산하려면 다음을 수행합니다.
printf %s "$var" | wc -c
에서는 다음으로 확장합니다 bash
.${#var}
수치변수에서. 바이트 수로 만들려면 로케일을 C로 수정하면 됩니다.
LC_ALL=C
echo "${#var}"
배열의 모든 요소에 대한 바이트 길이의 합을 얻으려면 요소를 연결하여 결과 문자열의 길이를 얻을 수 있습니다.
printf %s "${array[@]}" | wc -c
또는:
IFS=
concat="${array[*]}"
LC_ALL=C
echo "${#concat}"
zsh를 사용하면 다음을 수행할 수 있습니다.
() { set -o localoptions +o multibyte
echo ${#${(j[])array}}
}
여기서 매개변수 확장 플래그는 전역을 사용하는 j[sep]
대신 배열의 요소를 연결하는 데 사용됩니다 . 로케일을 수정하는 대신 get 옵션을 비활성화할 수 있습니다."${array[*]}"
$IFS
C
multibyte
특징≍바이트(이 작업은 로컬 익명 함수에서 수행됩니다).
바이트와 문자 간의 차이를 확인하려면 멀티바이트 인코딩을 문자 맵(예: UTF-8, GB18030, BIG5...)으로 사용하고 멀티바이트 인코딩 문자에 사용하는 로캘이 필요합니다. a
일반적으로 1바이트로 인코딩되므로 차이를 볼 수 없습니다. €
예를 들어 인코딩은 UTF-8에서는 3바이트이고 ISO8859-15에서는 1바이트입니다.
예( zsh
):
$ a=($'\xe2\x82\xac20' '$25' $'\xa420')
$ locale charmap
UTF-8
$ typeset -p a
typeset -a a=( €20 '$25' $'\M-$20' )
$ printf %s "${a[@]}" | wc -c
11
$ printf %s "${a[@]}" | wc -m
8
$ echo ${#${(j[])a}}
9
$ (){set -o localoptions +o multibyte; echo ${#${(j[])a}}}
11
문자 맵이 ISO8859-15인 로케일로 전환하는 경우:
$ locale charmap
ISO-8859-15
$ a=($'\xe2\x82\xac20' '$25' $'\xa420')
$ typeset -p a
typeset -a a=( â¬20 '$25' €20 )
$ printf %s "${a[@]}" | wc -c
11
$ printf %s "${a[@]}" | wc -m
11
$ echo ${#${(j[])a}}
11
$ (){set -o localoptions +o multibyte; echo ${#${(j[])a}}}
11
ISO8859-15는 단일 바이트 문자 인코딩이므로특징≍바이트거기.
추가 자료:
bash(또는 zsh)와 유사 wc -m
하지만 bash(또는 zsh)도 문자로 디코딩할 수 없는 바이트를 각각 한 문자로 계산합니다.