
쉼표로 구분된 목록을 반복하려면 IFS를 사용하는 것이 좋습니다. 예:여기. 그런데 그러고 보니
sentences="Hello World,Questions"
IFS=, sentences1=($sentences) # if we comment this line then loop is fixed
sentences2=$sentences
for sentence in ${sentences2[@]};
do
for i in $(seq 1 2);
do
#This is fine - prints a new word every line
#echo $sentence
#This is fine - prints new number every line
#echo $i
echo $i $sentence
done
done
생산하다
1
2 Hello World
1
2 Question
대신에
1 Hello World
2 Hello World
1 Question
2 Question
원하는. 했다?
답변1
여기서 주요 문제는 두 번째 줄인 가 IFS=, sentences1=($sentences)
IFS를 영구적으로 ","로 설정한다는 것입니다. 이는 스크립트의 나머지 부분 전체에서 이상하고 예상치 못한 구문 분석 동작이 발생한다는 것을 의미합니다. 와 같은 경우에는 IFS=, read ...
IFS 할당이 명령에만 적용되는 것으로 처리되므로 이런 일이 발생하지 않습니다 read
. 하지만 에는 IFS=, sentences1=($sentences)
실제 명령이 없고 할당만 있으므로 할당은 전체 셸에 적용되는 것으로 처리됩니다.
이제 스크립트의 나머지 부분에서 무슨 일이 일어나는지 살펴보겠습니다. sentences2=$sentences
그냥 sentences
에 복사 sentences2
하므로 for sentence in ${sentences2[@]}
조금 이상합니다. sentences2
배열(단지 일반 문자열)이 아니므로 비트는 [@]
아무 작업도 수행하지 않지만 IFS는 여전히 ","이므로 "Hello World" 및 "Questions"로 "단어 분할"을 가져옵니다. 즉, 올바른 결과를 얻었지만 잘못된 이유가 있습니다.
for sentence in "${sentences2[@]}"
(참고: 실제 배열인 경우 요소가 단어로 분할되는 것을 방지하기 위해 주위에 큰따옴표를 사용하는 것이 좋습니다 .)
다음 명령인 는 for i in $(seq 1 2)
실제 문제가 시작되는 곳입니다. seq 1 2
"1[newline]2[newline]"을 인쇄하고 $( )
구문이 후행 줄 바꿈을 다듬은 다음 "1[newline]2"가 단어 분할됩니다. 하지만 거기에 쉼표가 없기 때문에 한 단어로 처리됩니다. 개행 문자를 포함합니다). 따라서 내부 루프는 i
"1[newline]2"로 설정되어 한 번만 실행됩니다.
다음 줄 , echo $i $sentence
은 "1[newline]2", 공백, 의 내용을 인쇄합니다 sentence
. sentence
"Hello World"로 설정된 첫 번째 반복에서는 다음이 인쇄됩니다.
1
2 Hello World
...가운데에 줄 바꿈이 있으면 두 가지가 인쇄되는 것처럼 보이지만 실제로는 echo
줄 바꿈이 포함된 항목일 뿐입니다.
따라서 두 가지 큰 권장 사항은 다음과 같습니다. 첫째, IFS를 변경할 때 나중에 다시 변경하십시오. 둘째, 예상치 못한 단어 분할(및 와일드카드 확장)을 방지하려면 항상 변수 참조를 큰따옴표로 묶으십시오. 스크립트로 얻은 내용은 다음과 같습니다.
#!/bin/bash
sentences="Hello World,Questions"
saveIFS="$IFS"
IFS=, sentences1=($sentences)
IFS="$saveIFS" # Set IFS back to normal!
for sentence in "${sentences1[@]}"; do # Note double-quotes, and sentences1 is
an actual array
for i in $(seq 1 2); do # No double-quotes, we *want* seq's output to be spli
t
echo "$i" "$sentence" # Double-quotes for safety
done
done
답변2
이유가 무엇인지 모르겠지만 irc://freenode/bash가 솔루션을 제공합니다.
while IFS=, read -ra items; do
for item in "${items[@]}"; do
for i in {1..3}; do
printf '%d %s\n' "$i" "$item"
done
done
done <<< "Hello World,Questions,Answers"
제대로 인쇄됩니다.