Bash에는 두 가지 루프 형식이 있어요:
for문항목 목록을 순회하려면 for문을 사용해요.
for varname in words; do COMMANDS; done
words는 단어 분할과 파일명 확장을 통해 펼쳐져요(Quoting 개념에서 배운 내용이에요).
각 단어는 차례로 varname에 할당되고, COMMANDS가 실행돼요.
for문이 언제 유용한지 보여 주는 몇 가지 예시예요.
여러 파일에 대해 명령을 실행해요.
# source all the bash library files in the current directory
for file in ./*.bash; do
source "$file"
done
스크립트나 함수의 각 매개변수에 대해 명령을 실행해요.
for arg in "$@"; do
echo "argument: ${arg}"
done
어떤 명령의 출력에서 공백으로 구분된 각 단어마다 명령을 실행해요.
for i in $(seq 10); do
echo "${i} squared is $((i * i))"
done
이 방식에 대한 몇 가지 경고는 나중에 살펴볼 거예요.
for문Bash에는 산술 루프도 있어요. 다른 프로그래밍 언어를 써 본 사람이라면 어느 정도 익숙하게 보일 거예요.
for ((INITIALIZATION; CONDITION; INCREMENT)); do COMMANDS; done
Bash에서 이중 괄호는 산술 문맥을 나타내요(Bash 산술에 대해서는 나중 개념에서 더 살펴볼 거예요).
위의 seq를 사용한 예시는 이렇게 쓸 수 있어요.
for ((i = 1; i <= 10; i++)); do
echo "${i} squared is $((i * i))"
done
for문을 쓰지 말아야 할 때자주 보게 되는 안티 패턴이에요. cat의 출력을 순회하는 것이죠.
for line in $(cat some.file); do
do_something_with "$line"
done
이건 두 가지 면에서 잘못됐어요.
for문은 파일의 줄이 아니라 파일의 단어 를 순회하고 있어요.Quoting 개념에서 배웠듯이, 단어 분할은 IFS 변수로 제어할 수 있고 파일명 확장은 끌 수 있어요.
하지만 이 방법은 깨지기 쉬운 해결책인 경우가 많아요.
for는 파일의 줄을 순회하는 데 잘못된 방법이에요.
파일을 읽는 관용적인 방법은 while문을 사용하는 거예요.
while문어떤 조건이 참인 동안 명령을 반복하려면 while을 사용해요.
while CONDITION_COMMANDS; do COMMANDS; done
if와 마찬가지로(Conditionals 개념에서 배웠듯이, CONDITION_COMMANDS에 특별한 문법은 없어요.
명령 목록의 종료 상태가 "true" 또는 "false"를 결정해요.
break 명령은 루프 밖으로 빠져나가요.
제어는 루프의 done 종결자 다음 명령부터 이어져요.
continue 명령은 루프의 다음 반복으로 건너뛰어요.
앞서 말했듯이, 파일을 읽는 관용적인 방법은 while문이에요.
while IFS= read -r line; do
do_something_with "$line"
done < some.file
파일의 내용은 < 리다이렉션을 통해 루프의 입력으로 들어가요.
read 명령은 입력에서 한 줄 전체를 읽을 수 있으면 "true"를 반환해요.
입력이 다 소진되거나 마지막 줄이 줄 바꿈 없이 끝나면 read는 "false"를 반환해요.
마지막 줄이 줄 바꿈으로 끝나지 않는 경우에도 파일의 줄을 읽는 진정으로 관용적인 방법은
while IFS= read -r line || [[ -n "$line" ]]; do ...
-r 옵션은 read가 역슬래시 시퀀스를 치환하지 않도록 해요. 역슬래시는 그냥 평범한 문자예요.
IFS=는 read 명령이 실행되는 동안에만 IFS에 빈 문자열을 할당해요.
이렇게 하면 단어 분할이 일시적으로 꺼져서 들어오는 텍스트 줄의 앞뒤 공백이 그대로 유지돼요.
until문until 구문은 어떤 조건이 거짓인 동안 명령을 반복해요.
루프는 조건이 참이 될 때까지 반복해요.
until CONDITION_COMMANDS; do COMMANDS; done
until을 사용하는 경우는 드물어요.
"while not" 루프를 사용하는 경우가 더 흔해요.
while ! CONDITION_COMANDS; do ...
때로는 영원히 반복하고 싶을 때가 있어요. 두 가지 방법이 있어요.
항상 성공 종료 상태를 가지는 조건을 사용하는 while 루프
while true; do ...
식이 비어 있는 산술 for 루프
for ((;;)); do ...
명시적인 do-while 구문은 없지만, 같은 효과를 낼 수 있어요:
while true; do
COMMANDS
if END_CONDITION; then
break
fi
done