LINUX/리눅스 쉘 스크립트 바이블 정리

[리눅스 바이블] 13. 반복문 사용하기

은재정 2022. 3. 14. 21:56

 

for 명령

다음은 bash 쉘 for 문의 기본 형식이다.

for var in list
do
	commands
done

 

#!/bin/bash
for test in A B C D E
do
    echo "test: $test"
done


다만 목록안에 홑따옴표(')가 있다면 bash 쉘은 이를 구분자로 인식한다.

따라서 \를 써서 이스케이프 처리를 해주거나, 곁따옴표로 둘러싸야 한다.

또는 우리가 원하는 데이터 값 사이에 빈칸이 있다면 이를 겹따옴표로 감싸야 한다.

 

직접적인 목록말고도 명령의 출력을 사용할 수도 있다.

#!/bin/bash

file="states"

for state in $(cat $file)
do
    echo "Visit beautiful $state"
done

 

위처럼 명령의 출력을 읽을 때도 구분자로 빈 칸을 사용하는데, 원하는 데이터에 빈칸이 포함된다면 문제가 된다.

이 문제의 원인은 내부 필드 분리 구분자(IFS)라고 하는 특수한 환경 변수인 IFS 때문이다.

bash 쉘은 기본적으로 빈 칸, 탭(\t), 개행(\n) 세 문자를 필드 구분을 위한 기호로 간주한다.

따라서 이 문제를 해결하기 위해서는 쉘 스크립트에서 IFS 환경 변수 값을 바꿀 수 있다.

 

for 반복문을 사용해서 어떤 디렉토리 안의 파일을 자동으로 읽을수도 있다. 다음은 예시이다.

#!/bin/bash

for file in /home/user/test/*
do
    if [ -d "$file" ]; then
        echo "$file is a directory"
    elif [ -f "$file ]; then
        echo "$file is a file"
    fi
done

 

C 스타일 for 명령

C 스타일 bash의 for 명령을 사용할수도 있는데, 아래는 기본형식과 예제이다.

for (( variable assign ; condition ; iteration process ))
#!/bin/bash

for (( i=1; i <=10; i++ ))
do
	echo "The next number is $i"
done

 

while 명령

다음은 while 명령의 기본 형식이다.

while test command
do
	other commands
done

 

테스트 명령의 가장 일반적인 사용법은 대괄호를 사용하는 것이다.

#!/bin/bash

var1=10
while [ $var1 -gt 0 ]
do
    echo "var1: $var1"
    var1=$[ $var1 - 1]
done

 

while 문의 줄에 여러 테스트 명령을 정의할 수도 있다.

#!/bin/bash

var1=10
while echo $var1 
	[ $var1 -ge 0 ]
do
    echo "This is inside the loop"
    var1=$[ $var1 - 1 ]
done

 

 

until 명령

until 명령은 while 명령과는 정반대로 작동한다.

#!/bin/bash

var1=100
until [ $var1 -eq 0 ]
do
    echo $var1
    var1=$[ $var1 - 25 ]
done

 

파일 데이터에 대한 반복 작업

파일 내부 데이터에 대해 차례대로 반복 작업을 하고 싶다면 위에서 기술한 중첩 루프를 사용하고

IFS 환경 변수를 변경함으로써 할 수 있다. 다음은 /etc/passwd 파일에 대한 예시이다.

#!/bin/bash

IFS.OLD=$IFS
IFS=$'\n'
for entry in $(cat /etc/passwd)
do
    echo "Values in $entry - "
	IFS=:
    for value in $entry
    do
    	echo "$value "
    done
    IFS=$IFS.OLD
done

 

루프 제어

다른 프로그래밍 언어와 마찬가지로 bash 쉘 스크립트 언어에서도 break, continue와 같은 키워드를 사용해서

루프의 반복을 제어할 수 있다.

 

다만 두 가지 명령 모두 빠져나갈 수 있는 루프의 단계인 n을 커맨드라인 매개변수 값으로 가질 수 있다.

#!/bin/bash

for (( a = 1; a < 4; a++ ))
do
	echo "Outer loop: $a"
    for (( b =1; b < 100; b++ ))
    do
    	if [ $b -gt 4]; then
        	break 2
        fi
        echo " Inner loop: $b"
	done
done

for (( a = 1; a <= 5; a++ ))
do
	echo "Iteration $a:"
    for (( b = 1; b < 3; b ++ ))
    do
    	if [ $a -gt 2 ] && [ $a -lt 4 ]; then
        	continue 2
        fi
    	var3=$[ $a * $b ]
        echo " The result of $a * $b is $var3"
    done
done

 

루프의 출력 처리하기

쉘 스크립트에서 루프의 출력을 파이프 또는 리다이렉트할 수 있다. done 명령의 끝에 덧붙이면 된다.

#!/bin/bash

for file in /home/user/*
do
	if [ -d "$file" ]; then
    	echo "$file is a directory"
    elif
		echo "$file is a file"
    fi
done > output.txt

for alphabet in b c d a e
do
	echo "Alphabet: $alphabet"
done | sort

 

활용 예제

다음은 실행 파일을 찾는 예제이다.

#!/bin/bash

IFS=:
for folder in $PATH
do
	echo "$folder:"
    for file in $folder/*
    do
    	if [ -x $file ]; then
        echo " $file"
        fi
    done
done

 

다음은 여러 개의 사용자 계정을 만드는 예제로, 인풋 리다이렉션을 사용한다.

#!/bin/bash

input="users.csv"
while IFS=',' read -r userid name
do
	echo "adding $userid"
    useradd -c "$name" -m $userid
done < "$input"