문자열을 배열로 변환하려고 합니다 string=11111001
. 해당 배열 인덱스를 호출하여 액세스할 수 있습니다.
arr[0]=1, arr[1]=0
저는 쉘 스크립팅을 처음 접했고 읽은 내용에 구분 기호가 없어서 막혔습니다.
누구든지 나를 도와줄 수 있나요?
답변1
bash
이 형식은 문자열 분할을 통해 구현되었습니다.
$ word="word"
$ printf "%s\n" "${word:0:1}"
w
$ printf "%s\n" "${word:1:1}"
o
구문은 ${variable:start:length}
이며 다음을 반환합니다.length
다음으로 시작하는 문자start
ᵗʰ 문자(0 인덱스).
$ printf "%s\n" "${word:2:2}"
rd
답변2
완전성을 위해 ,를 사용하여 zsh
문자열을 다음과 같이 분할합니다.
그것은특징요소:
chars=( ${(s[])string} )
( $string
유효한 문자의 일부를 형성하지 않는 바이트가 포함된 경우 각 바이트는 여전히 별도의 요소로 저장됩니다.)
그것은바이트요소
동일한 작업을 수행할 수 있지만 설정을 해제한 후에는멀티바이트예를 들어 로컬 익명 함수의 옵션:
(){ set -o localoptions +o multibyte
bytes=( ${(s[])string} )
}
그것은문자소 클러스터요소.
PCRE의 기능을 사용하여 다음과 결합할 수 있습니다 \X
.
zmodload zsh/pcre
(){
graphemes=()
local rest=$string match
pcre_compile -s '(\X)\K.*'
while pcre_match -v rest -- "$rest"; do
graphemes+=($match[1])
done
}
(입력에 로케일의 문자 맵에서 올바르게 인코딩된 텍스트가 포함되어 있다고 가정).
의 경우 string=$'Ste\u0301phane'
다음이 제공됩니다.
chars=( S t e ́ p h a n e )
bytes=( S t e $'\M-L' $'\M-\C-A' p h a n e )
graphemes=( S t é p h a n e )
e
+U+0301 자소 클러스터(디스플레이 장치는 일반적으로 é
사전 구성된 U+00E9와 동일하게 표시됨)가 2개의 문자(U+0065 및 U+0301)로 구성되므로 문자 맵 로케일로 UTF-8을 사용합니다 . 첫 번째는 1바이트(0x65)로 인코딩되고 두 번째는 2바이트(0xcc 0x81, Meta-L 및 Meta-Ctrl-A라고도 함)로 인코딩됩니다.
ASCII 문자(예: 귀하의 문자)로만 구성된 문자열의 경우 11111001
이 세 문자는 동일합니다.
ksh/bash를 제외한 다른 모든 쉘에서와 마찬가지로 배열 인덱싱 은 zsh
0이 아닌 1에서 시작됩니다.
답변3
문자열을 개별 문자로 분할할 수 있습니다.
string=11111001
echo "$string" | grep -o .
배열로 다시 읽습니다.
readarray -t arr <<<"$(grep -o . <<<"$string")"
그러면 물론 모든 문자가 arr
배열의 모든 인덱스에 있게 됩니다.
$ declare -p arr
declare -a arr=([0]="1" [1]="1" [2]="1" [3]="1" [4]="1" [5]="0" [6]="0" [7]="1")
하지만 bash가 각 개별 문자에 직접 액세스할 수 있다면 왜 새 배열을 만들어야 할까요? 다음과 같이:
$ string=11111001
echo "${string:5:1}" "${string:7:1}"
0 1
${parameter:offset:length}
에 대해 읽다 man bash
.
답변4
bash
4.4 이상 에서는 bash
변수에 NUL 문자를 저장할 수 없으므로 다른 유틸리티를 호출하여 분할을 수행하고 NUL로 구분된 결과를 인쇄할 수 있습니다 readarray -td ''
. .
시스템이 GNU 구현과 함께 제공되는 경우 grep
다음을 수행할 수 있습니다.
readarray -td '' bytes < <(printf %s "$string" | LC_ALL=C grep -zo .)
readarray -td '' chars < <(printf %s "$string" | grep -zo .)
readarray -td '' graphemes < <(printf %s "$string" | grep -zPo '\X')
첫 번째를 제외하고 모두 로케일에서 유효한 문자의 일부를 형성하지 않는 바이트를 건너뜁니다(적어도 GNU grep
3.4에서는). 예를 들어 string=$'Ste\u0301phane \\\xf0\x80z.'
UTF-8 로케일(후행 부분은 유효한 UTF-8을 형성하지 않음)에서는 다음이 제공됩니다.
declare -a bytes=([0]="S" [1]="t" [2]="e" [3]=$'\314' [4]=$'\201' [5]="p" [6]="h" [7]="a" [8]="n" [9]="e" [10]=" " [11]="\\" [12]=$'\360' [13]=$'\200' [14]="z" [15]=".")
declare -a chars=([0]="S" [1]="t" [2]="e" [3]="́" [4]="p" [5]="h" [6]="a" [7]="n" [8]="e" [9]=" " [10]="\\" [11]="z" [12]=".")
declare -a graphemes=([0]="S" [1]="t" [2]="é" [3]="p" [4]="h" [5]="a" [6]="n" [7]="e" [8]=" " [9]="\\" [10]="z" [11]=".")
GNU 시스템이 아니고 $string
유효한 UTF-8 텍스트가 포함되어 있다고 가정하면 다음을 사용할 수 있습니다 perl
.
readarray -td '' bytes < <(perl -0le 'print for split "", shift' -- "$string")
readarray -td '' chars < <(perl -CSA -0le 'print for split "", shift' -- "$string")
readarray -td '' graphemes < <(perl -CSA -0le 'print for shift =~ /\X/g' -- "$string")