IFS를 사용하여 문자열을 문자로 분할하고 공백/널, 공백 및 문자 없이 읽는 방법-?

IFS를 사용하여 문자열을 문자로 분할하고 공백/널, 공백 및 문자 없이 읽는 방법-?

나는 밧줄을 가지고 있습니다 -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에서 아무것도 분할할 수 없습니다(가지다캐릭터가 됩니다.) rd 사이에는 문자가 없습니다 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- '리터럴 백슬래시가 할당됩니다 . IFS8진수 이스케이프는 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>    

하지만 솔직히 말해서, 이 괴물의 유일한 목적은 아마도 쉘 언어 세부 사항에 대한 심층적인 지식을 가정하여 초보자를 겁주고 바보들에게 깊은 인상을 남기는 것일 것입니다 ;-)

관련 정보