16. 코드 블럭 재지향
while
, until
, for
루프의 코드 블럭, 심지어 if
/then
테스트문 블럭도 표준입력의 재지향을 받아 들일 수 있다. 함수조차도 이런 형태의 재지향을 할 수 있다. 이렇게 하려면, 해당 코드 블럭의 제일 끝에 <
연산자를 두면 된다.
예제) 재지향된 while 루프
#!/bin/bash
# "names.data" 파일의 내용
# Hello
# Bye
# Smith
if [ -z "$1" ]; then
# 파일이름이 지정되지 않을 경우의 기본값
Filename=names.data
else
Filename="$1"
fi
count=0
while [ "$name" != "Smith" ]; do
# 표준입력이 아니라 "$Filename"에서 읽음
read name
echo "$name"
count=$(($count + 1))
# 표준입력을 "$Filename" 파일로 재지향
done <"$Filename"
# Hello
# Bye
# Smith
echo "$count 개의 이름을 읽었습니다."
# 3 개의 이름을 읽었습니다.
exit 0
몇몇 오래된 셸 스크립트 언어에서는 재지향된 루프가 서브셸로 돌게 된다. 그렇기 때문에, $count
가 루프 밖에서 초기화되어 0을 리턴한다.
#!/bin/bash
# "names.data" 파일의 내용
# Hello
# Bye
# Smith
if [ -z "$1" ]; then
# 파일이름이 지정되지 않을 경우의 기본값
Filename=names.data
else
Filename="$1"
fi
# 표준입력을 3번 파일 디스크립터로 임시 저장
exec 3<&0
# 표준입력을 재지향
exec 0<"$Filename"
count=0
while [ "$name" != "Smith" ]; do
# 표준입력이 아니라 "$Filename"에서 읽음
read name
echo "$name"
count=$(($count + 1))
# 표준입력을 "$Filename" 파일로 재지향
done <"$Filename"
# Hello
# Bye
# Smith
# 원래 표준입력 복구
exec 0<&3
# 임시 파일 디스크립터를 닫음
exec 3<&-
echo "$count 개의 이름을 읽었습니다."
# 3 개의 이름을 읽었습니다.
exit 0
#!/bin/bash
# "names.data" 파일의 내용
# Hello
# Bye
# Smith
if [ -z "$1" ]; then
# 파일이름이 지정되지 않을 경우의 기본값
Filename=names.data
else
Filename="$1"
fi
# 표준입력을 3번 파일 디스크립터로 임시 저장
exec 3<&0
# 표준입력을 재지향
exec 0<"$Filename"
count=0
# while [ "$name" != "Smith" ]; do
until [ "$name" = "Smith" ]; do
# 표준입력이 아니라 "$Filename"에서 읽음
read name
echo "$name"
count=$(($count + 1))
# 표준입력을 "$Filename" 파일로 재지향
done <"$Filename"
# Hello
# Bye
# Smith
# 원래 표준입력 복구
exec 0<&3
# 임시 파일 디스크립터를 닫음
exec 3<&-
echo "$count 개의 이름을 읽었습니다."
# 3 개의 이름을 읽었습니다.
exit 0
#!/bin/bash
# "names.data" 파일의 내용
# Hello
# Bye
# Smith
if [ -z "$1" ]; then
# 파일이름이 지정되지 않을 경우의 기본값
Filename=names.data
else
Filename="$1"
fi
# 대상 파일의 줄 수
line_count=$(wc "$Filename" | awk '{ print $1 }')
# line_count=$(wc < "Filename")
for name in $(seq "$line_count"); do
read name
echo "$name"
if [ "$name" = "Smith" ]; then
break
fi
done <"$Filename"
# Hello
# Bye
# Smith
echo "$line_count 개의 이름을 읽었습니다."
# 3 개의 이름을 읽었습니다.
exit 0
#!/bin/bash
# "names.data" 파일의 내용
# Hello
# Bye
# Smith
if [ -z "$1" ]; then
# 파일이름이 지정되지 않을 경우의 기본값
Filename=names.data
else
Filename="$1"
fi
# 결과를 저장할 파일이름
Savefile="${Filename}.new"
# "read" 시에 마지막 입력이 될 이름
FinalName="Jonah"
# 대상 파일의 줄 수
line_count=$(wc "$Filename" | awk '{ print $1 }')
# line_count=$(wc < "Filename")
for name in $(seq "$line_count"); do
read name
echo "$name"
if [ "$name" = "Smith" ]; then
echo "$FinalName"
break
fi
# 표준입력을 "$Filename"으로 재지향하고
# 그 결과를 백업 파일로 저장
done <"$Filename" >"$Savefile"
# "names.data.new" 파일의 내용
# Hello
# Bye
# Smith
# Jonah
exit 0
#!/bin/bash
# "names.data" 파일의 내용
# Hello
# Bye
# Smith
if [ -z "$1" ]; then
# 파일이름이 지정되지 않을 경우의 기본값
Filename=names.data
else
Filename="$1"
fi
TRUE=1
# if True 또는 if :도 동작함
if [ "$TRUE" ]; then
read name
echo "$name"
fi <"$Filename"
# 파일의 첫 번째 줄만 읽어 들임
# "if/then" 테스트문은 루프 안에서 쓰이지 않는 한
# 반복해서 비교할 방법이 없음
exit 0