Linux

0402_Linux_Shell Programming_제어문 (2)_반복문

SW Kang 2021. 4. 2. 10:05

조건문

  • 조건에 따라 수행할 동작을 지정
    • if : 조건이 맞으면 실행, 아니면 패스
    • if~else : 조건이 맞으면 if 아래를 실행, 조건이 틀리면 else 아래를 실행, 양자택일
    • if~else if~else : 조건이 여러개. 첫 번째 조건이 맞으면 if 아래를 실행, 두번째 조건이 맞으면 두번째 else if 아래를 실행. 모든 조건이 틀리면 else 아래를 실행. 다지선다
  • 조건문의 문법 : if, then, fi

if (조건)

then

  (if 실행할 내용)

fi

if (조건)

then

  (if 실행할 내용)

else

  (else 실행할 내용)

fi

if (조건1)

then

  (if 조건1에 따라 실행할 내용)

elif (조건2)

then

  (elif의 조건2에 따라 실행할 내용)

elif (조건3)

then

  (elif의 조건3에 따라 실행할 내용)

else

  (모든 조건을 만족하지 않을 경우 실행할 내용)

fi

 

case = if~else if~else 와 유사한 동작. 다지선다

case 변수명 in

값1) 실행할 내용1 ;;

값2) 실행할 내용2 ;;

값3) 실행할 내용3 ;;

*) 실행할 내용4

esac

 

쉘 프로그래밍의 조건문에서의 ‘조건’

  • 명령의 실행 결과가 if의 조건으로 사용됨 : 종료상태(Exit Status)
    • 정상종료 : 0 (true)
    • 비정상종료 : 0이 아닌 모든 값 (false)
  • 일반적인 수치비교, 문자, 문자열 비교 : test
    • 수치비교
      • == : INT1 -eq INT2 (equal)
      • != : INT1 -ne INT2 (not equal)
      • > : INT1 -gt INT2 (greater than)
      • < : INT1 -lt INT2 (less than)
      • >= : INT1 -ge INT2 (greater or equal)
      • <= : INT1 -le INT2 (less or equal)
    • 문자비교
      • 문자열1 = 문자열2 : 문자열 1과 2가 같으면 참
      • 문자열1 != 문자열2 : 문자열 1과 2가 같지 않으면 참
      • 문자열 : 문자열이 NULL 이 아니면 참, NULL 이면 거짓
      • -z 문자열 : 문자열의 길이가 0이면 참, 아니면 거짓
      • -n 문자열 : 문자열의 길이가 0이 아니면 참, 아니면 거짓
    • test 명령어는 [ ] 로 대체 가능
    • ksh, bash 등 이후에 나온 쉘은 다음과 같은 기능도 사용가능
      • [[ ]] 를 사용하여 단순 비교 이외의 비교도 가능
      • [[ 문자열 = 패턴 ]] : 문자열에 패턴이 포함되어 있는가
      • [[ 문자열 != 패턴 ]] : 문자열에 패턴이 포함되지 않았는가
      • [[ 문자열1 > 문자열2 ]] : 문자열1과 2의 ASCII 대소비교
        • STR1=AA;  STR2=AB
        • [[ $STR1 > $STR2 ]]; echo $?
      • let을 사용하여 간단한 수치비교 가능 (( ))
      • (( 변수1 > 숫자 )) : 변수의 값이 숫자보다 큰가
      • (( 변수1 = 변수2 + 변수3 ))
        • (( NUM3=NUM1+NUM2 ))
    • 파일관련 조건 확인
      • [옵션] [파일명]
      • 옵션
        • -b : 블록 장치인지 확인
        • -c : 캐릭터 장치인지 확인
        • -d : 디렉토리인지 확인
        • -e : 종류에 상관없이 파일이 있는지 확인
        • -f : 일반 파일인지 확인
        • -r : test를 수행하는 사람이 파일의 읽기 권한을 가지고 있는가
        • -w : test를 수행하는 사람이 파일의 쓰기 권한을 가지고 있는가
        • -x : test를 수행하는 사람이 파일의 실행 권한을 가지고 있는가
        • -u : SetUID 가 설정되어 있는가
        • -g : SetGID가 설정되어 있는가
        • -k : StickyBit가 설정되어 있는가
    • test 사용시 조건의 논리합/논리곱
      • [ 조건1 -a 조건2 ] : 조건1과 조건2를 모두 만족하여야 참
      • [[ 조건1 && 조건2 ]] : 위와 동일
      • [ 조건1 -o 조건2 ] : 조건1과 조건2중 하나만 만족하면 참
      • [[ 조건1 || 조건2 ]] : 위와 동일

 

  • /usr/bin/true, /usr/bin/false : 다른 역할은 하지 않으면서 종료상태만 변경
  • ‘ : ’ : true 와 같은 역할

 

case 테스트

 

#!/bin/bash


echo "Input Fruits name : "

read FRUIT


if [ $FRUIT = 'apple' ]

then

        echo "APPLE"

elif [ $FRUIT = 'banana' ]

then

        echo "banana"

else

        echo "cherry"

fi


case $FRUIT in

apple)  echo APPLE ;;

banana) echo BANANA ;;

*)      echo cherry ;;

esac



연습문제

  1. 파일명을 입력받고, 입력받은 파일의 종류(일반파일, 디렉토리, 블록장치, 캐릭터장치…)가 무엇인지 출력하는 스크립트를 작성해보세요.

input filename : /etc/passwd

/etc/passwd : normal file


input filename : /dev/sda

/dev/sda : block device file


input filename : /tmp

/tmp : directory

 

  1. 숫자 두개와 연산자를 입력받아 계산 결과를 출력하는 프로그램을 작성해보세요\

input number: 10

input number: 20

operator : +

10 + 20 = 30

 

  1. df -h 명령을 사용해서 확인할 수 있는 ‘/’ 에 마운트된 장치의 사용량이 50%를 초과할 경우 메세지를 출력하는 프로그램을 작성하시오.

/dev/mapper/centos-root   47G  5.7G   42G  13% /


‘/’ USE% is under 50%

/dev/mapper/centos-root   47G  5.7G   42G  53% /


‘/’ USE% is over 50%

 

q1.sh

#!/bin/bash


echo -n "Input filename : "

read FILENAME


if [ -f $FILENAME ]

then

        echo "$FILENAME : normal file"

elif [ -d $FILENAME ]

then

        echo "$FILENAME : directory"

elif [ -b $FILENAME ]

then

        echo "$FILENAME : block device file"

elif [ -c $FILENAME ]

then

        echo "$FILENAME : character device file"

else

        echo "I don't know"

fi

q2.sh

#!/bin/bash


echo -n "Input number1 : "

read NUM1

echo -n "Input number2 : "

read NUM2


echo -n "Input operator : "

read OPER


case $OPER in

'+') echo "$NUM1 + $NUM2 = `expr $NUM1 + $NUM2`" ;;

'-') echo "$NUM1 - $NUM2 = `expr $NUM1 - $NUM2`" ;;

'/') echo "$NUM1 / $NUM2 = "`echo "scale=2;$NUM1/$NUM2" | bc` ;;

'*') echo "$NUM1 X $NUM2 = `expr $NUM1 \* $NUM2`" ;;

*) echo "ERROR!" ;;

esac

q3.sh

#!/bin/bash


DFRESULT="/dev/mapper/centos-root   47G  5.7G   42G  63% /"

echo "SAMPLE: $DFRESULT"


USEPERCENT=`echo $DFRESULT | awk '{ print $5 }'`

echo "Current USE% : "$USEPERCENT


USEPERCENT=`echo ${USEPERCENT:0:-1}`


if (( USEPERCENT>50 ))

then

        echo "OVER 50%!"

else

        echo "UNDER 50%!"

fi




=============================================================

 

반복문 (Loop)

  • 지정한 회수, 또는 조건에 따라 반복을 수행
  1. for 반복문

for(i=0;i<10;i++){

printf(“Hello!\n”)

}

 

C언어 등 일반적인 프로그래밍 언어의 반복문의 조건 형태

  • 초기식 : 특정 변수를 초기값으로 설정
  • 비교식 : 반복여부를 결정하기 위하여 조건을 확인
  • 증감식 : 조건에 사용되는 변수의 값을 변경

 

쉘 프로그래밍의 반복문 : for

 

for 변수 in [argument]

do

[실행할내용]

done

 

#!/bin/bash


for i in `ls`

do

echo $i

done

 

argument : 반복문에서 변수에 집어넣을 값의 리스트

  • 공백,개행 등으로 구분되어 있는 텍스트
  • 명령의 실행결과 : `명령어`
  • 파일의 내용 : `cat [파일이름]`
  • 변수의 값 : $변수명
  • 위치매개변수 : $*, $@, “$*”, “$@”

 

위치매개변수를 반복문의 argument로 사용할 경우

  • $*, $@ : 각 위치매개변수의 값을 그대로 나열하므로, 사이에 공백이 들어있는 하나의 매개변수를 분리함
  • “$*” : 전체 위치매개변수의 값을 하나의 문자열로 처리
  • “$@” : 위치매개변수 중 공백을 포함하고 있는 항목만 따로 ‘ ‘ 로 묶어서 처리

 

#!/bin/bash


for i in $*

for i in $@

for i in "$*"

for i in "$@"

do

echo $i

done

 

argument에 숫자 사용방법

  • 단순 숫자 나열 : 직접 반복문에 사용할 변수에 집어넣을 숫자를 나열
  • seq 명령 사용
    • seq [숫자] : 1부터 지정한 숫자까지 1씩 증가하며 출력
    • seq [숫자1] [숫자2] : 숫자1 부터 숫자2까지 1씩 증가하며 출력
    • seq [숫자1] [숫자2] [숫자3] : 숫자 1부터 숫자 3까지 숫자2 만큼씩 증가시키며 출력
  • 다른 프로그래밍 언어의 for 구문과 유사한 사용방법
    • for ((초기식;조건식;증감식))

 

#!/bin/bash


for i in `seq 20 -2 0`

do

echo "NUM = $i"

done

#!/bin/bash


for ((i=0;i<10;i++))

do

echo "NUM = $i"

done



  1. while

while  [조건]

do

[실행할 내용]

done

 

while의 동작

  • while 내부 명령을 실행하기 전 조건을 확인
  • 조건을 만족할 경우 (참일 경우) 실행
  • 조건을 만족하지 않을 경우 done 아래로 이동
  • 조건을 true 등 언제나 참인 조건으로 사용할 경우는 무한루프로 동작
  • 사용자가 입력하는 값을 변수에 집어넣어서 비교하여 종료하는 방식

 

#!/bin/bash


VAR=0


while [ $VAR -le 10 ]

do

echo $VAR

VAR=`expr $VAR + 1`

done

#!/bin/bash


STR=n


while [ $STR != y]

do

echo -n "Quit (y/n)? "

read STR

done

 

  • until : while 의 반대. 조건이 거짓일 경우에 반복 수행

 

until [조건]

do

[실행할 내용]

done

 

  1. 중첩 반복문 / break / continue

 

중첩 반복문

  • 반복문 내부에 반복문이 포함되는 형태
  • 내부 반복문은 외부 반복문이 한번 실행될 때마다 전체 반복을 수행
    • 구구단 :  단 / 곱할 수
    • 반복문1(단을 올리는 반복문)

 

do

반복문2 (곱할수를 올리는 반복문)

do

vi구구단 출력

done

done

 

#!/bin/bash


for i in `seq 2 9`

do

for j in `seq 2 9`

do

echo "$i X $j = `expr $i \* $j`"

done

done

 

break : 반복문을 탈출하는 용도

  • 반복문을 탈출하는 용도 (if 내에서 탈출하는 용도로는 사용할 수 없음)
  • 탈출위치는 현재 break가 사용된 반복문의 done 아래로 이동
  • 중첩 반복문에서 사용될 경우, 한 단계의 반복문만 탈출
  • break [숫자] : 한꺼번에 지정한 개수만큼의 반복문 탈출
  • exit : 반복문이 아니라 스크립트 전체를 종료
    • exit [숫자] : 스크립트를 종료하면서 종료상태값을 설정

 

while true

do

echo -n "Quit? (y/n) : "

read STR


if [ $STR = "y" ]

then

break

fi

done

for i in `seq 2 9`

do

for j in `seq 2 9`

do

if [ $j -gt 5 ]

then

# break 반복문 탈출

# break 2 반복문 2개 탈출

# exit 모든 반복문 즉시 탈출

fi

echo "$i X $j = `expr $i \* $j`"

done

done

for i in `seq 2 9`

do

for j in `seq 2 9`

do

if [ $j -gt 5 ]

then

break

fi

echo "$i X $j = `expr $i \* $j`"

done

done


# exit 0 스크립트 종료 후 종료 상태값 0으로 설정

# exit 1 스크립트 종료 후 종료 상태값 1로 설정

 

continue

  • 반복문의 흐름을 변경시키는 용도
  • continue를 만날 경우, 현재 있는 반복문의 조건 위치로 이동(do 앞으로)
  • continue [숫자] : 한꺼번에 지정된 개수만큼의 반복문 위로 올라감

 

#!/bin/bash


for i in 2 3 4 5 6 7 8 9

do

        for j in 1 2 3 4 5 6 7 8 9

        do

                if [ $j -eq 5 ]

                then

                        # continue

                        # continue 2

                fi


                echo "$i X $j ="`expr $i \* $j`

        done

done



q1) 어제 실습한 내용 중 숫자 입력받고 연산자 입력받아서 계산하는 프로그램

=> 위치매개변수를 사용하여 계산하도록

 

$ ./myexpr.sh 10 + 3

10 + 3 = 13

$ ./myexpr.sh 10 / 3

10 / 3 = 3.33