나는 밧줄을 가지고 있습니다 -w o rd
. 중요하지 않기 때문에 배열이나 배열
로 분할해야합니다 . 나는 다음을 시도했다 w o r d
'w' 'o' 'r' 'd'
IFS='\0- ' read -a string <<< "-w o rd"
echo ${string[*]}
rd
나누어지지 않았습니다. 어떻게 따로 만들 수 있나요?
답변1
IFS를 사용하여 bash에서 아무것도 분할할 수 없습니다(가지다캐릭터가 됩니다.) r
와 d
사이에는 문자가 없습니다 rd
. 공백이나 문자는 널 문자와 다르지 않습니다.
각 문자를 배열의 별도 요소로 원하는 경우 제가 생각할 수 있는 한 가지 방법은 각 문자를 개별적으로 읽고 이를 배열에 추가하는 것입니다(그리고 IFS를 사용하여 공백과 를 제거합니다 -
).
bash-4.4$ while IFS=' -' read -n1 c ; do [[ -n $c ]] && foo+=("$c"); done <<<"-w o rd"
bash-4.4$ declare -p foo
declare -a foo=([0]="w" [1]="o" [2]="r" [3]="d")
답변2
다음을 사용하여 원하지 않는 문자를 제거할 수 있습니다 ${var//pattern/replacement}
.
s='-w o rd'
s=${s//[- ]}
그런 다음 하위 문자열 확장을 사용하여 한 번에 한 문자를 선택합니다.
$ for ((i=0; i < ${#s}; i++)); do
echo ${s:i:1}; # or do whatever you like here
done
(적어도 내 시스템에서는 멀티바이트 문자도 처리하는 것 같습니다.)
백슬래시는 작은따옴표 안에 특별한 의미가 없기 때문에 IFS='\0- '
리터럴 백슬래시가 할당됩니다 . IFS
8진수 이스케이프는 Bash에서 작동 $'...'
하지만 Bash의 변수는 NUL 바이트를 포함할 수 없으므로 도움이 되지 않습니다. (문자열은 NUL에서 잘려서 x=$'foo\0bar'; printf "%q\n" "$x"
인쇄됩니다 foo
. 또한 @muru가 말한 대로 NUL 바이트로 분할하는 것은 각 문자 간 분할과 동일하지 않습니다.)
답변3
문자열이 너무 길지 않은 경우:
w='-w o rd baa'
w=${w//[!a-z]} # strip anything but lower case letters
eval echo '${w:'{0..10}':1}'
eval array=\( '${w:'{0..10}':1}' \)
echo "${array[@]}"
w o r d b a a
zsh
어리석은 것을 훨씬 더 나쁜 것, IFS 및 glob 안전으로 바꿀 수 있으며 , 및 bash
사이의 중괄호 및 변수 확장 의 상대적 순서를 고려할 수 있습니다 ksh
.
args(){ printf '<%s> ' "$@"; echo; }
w='-e a * () \n peek
fo*"x'"'q"
eval eval args "'\"\${w:'{0..$((${#w}-1))}':1}\"'"
eval eval 'array=\(' "'\"\${w:'{0..$((${#w}-1))}':1}\"'" '\)'
args "${array[@]}"
<-> <e> < > <a> < > <*> < > <(> <)> < > <\> <n> < > <p> <e> <e> <k> <
> < > <f> <o> <*> <"> <x> <'> <q>
하지만 솔직히 말해서, 이 괴물의 유일한 목적은 아마도 쉘 언어 세부 사항에 대한 심층적인 지식을 가정하여 초보자를 겁주고 바보들에게 깊은 인상을 남기는 것일 것입니다 ;-)