섹션 5. 비교와 루프문

 

리눅스 서버를 자동화하여 관리하기 위한 쉘 스크립트(Shell Script) 심화 강좌를 정리합니다.
출처 : inflearn

1. 조건문(if..else.fi)

linux:/home/shkim$ if true; then
> echo true
> else
> echo false
> fi
true
linux:/home/shkim$ if true; then echo true; else echo false; fi # 한줄로도 표현 가능 줄바꿈은 세미콜론 처리.
true

if 문(IF Statement)

  • style #1
    if COMMANDS
    then OTHER COMMANDS
    fi
    
  • style #2
    if COMMANDS
    then 
    OTHER COMMANDS
    fi
    
  • style #3
    if COMMANDS;then 
    OTHER COMMANDS
    fi
    

2. [..] vs [[..]]

linux:/home/shkim$ tom="Tom janks"
linux:/home/shkim$ deniro="Robert Deniro"
linux:/home/shkim$ [ $tom > $deniro ] # 대괄호는 테스트로 사용함, [..] 안에서 >< 문자는 리다이렉트로 해석된다.
-bash: $deniro: ambiguous redirect
linux:/home/shkim$ 
linux:/home/shkim$ [[ $tom > $deniro ]]
linux:/home/shkim$ echo $? # $?는 직전 명령의 성공,실패를 확인할 때 사용 
0 # 참
linux:/home/shkim$ [ $tom = $deniro ] # ==> [ Tom hanks = Robert Deniro ] // 공백으로 인한 에러
-bash: [: too many arguments
linux:/home/shkim$ [ "$tom" = "$deniro" ]
linux:/home/shkim$ [ "Tom hanks" = "Robert Deniro" ]
linux:/home/shkim$ [[ $tom = $deniro ]]; echo $?
1
linux:/home/shkim$ [[ $tom > $deniro ]]; echo $?
0

3. 인용부호 사용시 주의사항

linux:/home/shkim$ VAR=; if [ $VAR = "" ];then echo true; else echo false;fi
-bash: [: =: unary operator expected
false

#  위의 내용을 해석하면 다음과 같음 [   = ""]
linux:/home/shkim$ VAR=; if [ "$VAR" = "" ];then echo true; else echo false;fi
true

#  인용부호를 사용하여 해결
linux:/home/shkim$ VAR=; if [[ $VAR = "" ]];then echo true; else echo false;fi
true

# [[ ]] 테스트 부호를 입력하여 인용문자 생략 할 수 있음.

4. 비교 메타 문자들

linux:/home/shkim/a$ touch hello.txt
linux:/home/shkim/a$ if [ ! -f "hello.txt.bak" ]; then
>  cp "hello.txt" "hello.txt.bak"
> fi
linux:/home/shkim/a$ ls
hello.txt  hello.txt.bak

# 현재 디렉토리에 hello.txt.bak 파일이 없으면 hello.txt 파일을 hello.txt.bak 복사본 생성
# -f // 파일의 존재여부 확인 할 때 사용
Name Description
-e FILE 파일이 있는 경우 True 입니다.
-f FILE 파일이 일반 파일인 경우 True 입니다.
-d FILE 파일이 디렉터리인 경우 True 입니다.
-h FILE 파일이 심볼 링크인 경우 True 입니다.
-p PIPE 파이프가 있는 경우 True 입니다.
-r FILE 사용자가 파일을 읽을 수 있는 경우 True 입니다.
-e FILE 파일이 있는 경우 True 입니다.
-s FILE 파일이 존재하며 비어 있지 않은 경우 True 입니다.
-t FD 터미널에서 FD가 열려 있는 경우 True 입니다.
-w FILE 사용자가 파일을 쓸 수 있는 경우 True 입니다.
linux:/home/shkim$ if (( $? )); 
>    then echo 'Please run using "bash" or "sh", but not "." or "source"' >&2; 
>    exit 1; 
>fi

# 앞선 명령어가 비정상 실행 일 경우 실행을 무효화 시키는 스크립트.
# 어떤 경로에 파일 목록이 있는지 확인
linux:/home/shkim$ if [[ $(ls -A) ]]; then
>     echo "there are files"
> else
>     echo "no files found"
> fi
there are files
linux:/home/shkim/shell_cmd$ cat sleep.sh 
#!/bin/bash

while true; do
  sleep 1;
done

linux:/home/shkim/shell_cmd$ ps
  PID TTY          TIME CMD
10386 pts/0    00:00:00 bash
11304 pts/0    00:00:00 sleep.sh
11417 pts/0    00:00:00 sleep
11423 pts/0    00:00:00 ps

linux:/home/shkim/shell_cmd$ result=`ps aux | grep -i "sleep.sh" | grep -v "grep" | wc -l`
linux:/home/shkim/shell_cmd$ if [ $result -ge 1 ] # 크거나 같다 (greater and equal)
> then
>     echo "script is running"
> else
>     echo "script is not running"
> fi
script is running
linux:/home/shkim/shell_cmd$ ps
  PID TTY          TIME CMD
10386 pts/0    00:00:00 bash
11575 pts/0    00:00:00 sleep.sh
12021 pts/0    00:00:00 sleep
12027 pts/0    00:00:00 ps
linux:/home/shkim/shell_cmd$ kill 11575 12021
-bash: kill: (12021) - No such process
[1]+  Terminated              ./sleep.sh
linux:/home/shkim/shell_cmd$ ps
  PID TTY          TIME CMD
10386 pts/0    00:00:00 bash
12077 pts/0    00:00:00 ps
linux:/home/shkim/shell_cmd$ result=`ps aux | grep -i "sleep.sh" | grep -v "grep" | wc -l`
linux:/home/shkim/shell_cmd$ if [ $result -ge 1 ]; then     echo "script is runngin"; else     echo "script is not running"; fi
script is not running

[ ] 을 이용한 TEST

Name Description
-x FILE 파일이 실행 가능한 경우 True 입니다.
-O FILE 파일이 사용자가 효과적으로 소유하는 경우 True 입니다.
-G FILE 파일이 그룹에 의해 효과적으로 소유되는 경우 가능한 경우 True 입니다.
FILE -nt FILE 첫 번째 파일이 두 번째 파일보다 최신이면 경우 True 입니다.
FILE -ot FILE 첫 번째 파일이 두 번째 파일보다 오래된 경우 True 입니다.
-z STRING 문자열이 비어 있으면 True 입니다.(길이가 0임)
-n STRING 문자열이 비어있지 않은 경우 True 입니다.(길이 0이 아님)
STRING = STRING 첫 번째 문자열이 두 번째 문자열과 동일한 경우 True 입니다.
STRING != STRING 첫 번째 문자열이 두 번째 문자열과 동일하지 않은 경우 True 입니다.
STRING < STRING 첫 번째 문자열이 두 번째 문자열보다 먼저 정렬되는 경우 True 입니다.
STRING > STRING 첫 번째 문자열이 두 번째 문자열 뒤에 정렬되는 경우 True 입니다.
EXPR -a EXPR 두 식이 모두 참이면 참입니다.(logical AND)
EXPR -o EXPR 두 식 중 하나가 참이면 참입니다.(logical OR)
! EXPR 표현식의 결과를 반전합니다.(logical NOT)
INT -eq INT 두 정수가 동일한 경우 True 입니다.
INT -ne INT 정수가 동일하지 않은 경우 True 입니다.
INT -lt INT 정수가 동일하지 않은 경우 True 입니다.
INT -gt INT 첫 번째 정수가 두 번째 정수보다 큰 경우 True 입니다.
INT -le INT 첫 번째 정수가 두 번째 정수보다 작거나 같으면 True 입니다.
INT -ge INT 첫 번째 정수가 두 번째 정수보다 크거나 같은 경우 True 입니다.
STRING =(or ==) PATTERN [ 과 같은 문자열 비교는 아니지만 패턴 일치가 수행됩니다. 문자열이 글로브 패턴과 일치하는 경우 Treu 입니다.
STRING != PATTERN [ 과 같은 문자열 비교는 아니지만 패턴 일치가 수행됩니다. 문자열이 글로브 패턴과 일치하지 않는 경우 True 입니다.
STRING =~ REGEX 문자열이 regex 패턴과 일차히는 경우 True 입니다.
(EXPR) 괄호를 사용하여 평가 우선 순위를 변경 할 수 있습니다.
EXPR && EXPR 테스트의 -a 연산자와 매우 유사하지만 첫 번째 표현식이 이미 거짓으로 판명되면 두 번째 표현식을 평가하지 않습니다.
EXPR || EXPR 테스트의 -o 연산자와 매우 유사하지만 첫 번째 표현식이 이미 사실인 경우 두 번째 표현식을 평가하지 않습니다.
  • [ ] 보다는 [[ ]]를 사용하는 것이 좋습니다. *

실습(DRILL)

  • 스크립트 뒤에 전달인자가 있어야 실행되는 스크립트를 작성해 보세요.
#!/bin/bash

if [ -z "$1" ] ; then
    echo "usage: $0 directory"
    exit
fi
    echo "Have a nice day!"

6. while 루프

# 1초에 한번씩 Hello world 출력
linux:/home/shkim/a$ while true; do
> echo "Hello world"
> sleep 1
> done
Hello world
Hello world
Hello world
^C
linux:/home/shkim/a$ 
# 1초에 한번씩 비프음 발생
linux:/home/shkim/a$ while true; do
> echo -n -e "\a";
> sleep 1;
> done
linux:/home/shkim/a$ for no in `eval echo {0..$COUNT}`; do
> echo $no
> done
0
1
2
3
4
5
6
7
8
9
10
linux:/home/shkim/a$ 
linux:/home/shkim/a$ eval echo {0..$COUNT}
0 1 2 3 4 5 6 7 8 9 10
linux:/home/shkim/a$ 

실습(DRILL)

  • 1부터 100까지 더하는 스크립트를 작성해 보세요.
#!/bin/bash

sum=0
for num in {1..100}; do
    (( sum = sum+num ))
done 

echo "SUM=$sum"

7. for..in 루프

8. for((;;)) 루프

9. 명령어(date)

10. 루프문과 glob

11. 명령어(seq)

12. case

13. getopts

14. select