[클라우드 With리눅스/쉘프로그래밍(5) - for,while,select,continue and break]

SooYeon Yeon·2022년 8월 22일

클라우드 With리눅스

목록 보기
30/39

반복문

for문

for 변수 in 리스트
do
	반복할 문장
done
for test in I don't know if this'll work
do
	echo "word:$test"
done

-----------------------------------------
출력결과
word:I
word:dont know if thisll
word:work
  • 쉘은 홀따옴표를 만나면 그 사이 값을 단일한 데이터 값으로 봄
for test in I "don't" know if "this'll" work
do
	echo "word:$test"
done

-----------------------------------------
출력결과
word:I
word:don't
word:know
word:if
word:this'll
word:work
file="states"
for state in $(cat $file)
do
	echo "$state"
done
-------------------------------
출력결과
busan
seoul
daegu
gwangju

Quiz

[root@sooyeon cloud]# set | grep IFS
IFS=$' \t\n'
[root@sooyeon cloud]# cat /etc/passwd | grep user1
user1:x:1000:1000:user1:/home/user1:/bin/bash

IFS에 :를 추가하여 해당 cat 문장 하나하나를 for문에 넣을 수 있도록 변경하기

IFS=$’\n’:;” 로 여러개도 가능

#!/bin/bash
IFS=:

for word in $(cat /etc/passwd | grep user1)
do
        echo "list:$word";
done

gawk -F: 각각을 : 로 구분한다는 뜻

[root@sooyeon 0726]# cat /etc/passwd | grep user1
user1:x:1000:1000:user1:/home/user1:/bin/bash
[root@sooyeon 0726]# cat /etc/passwd | grep user1 | gawk -F: '{print $6}'
/home/user1
  • IFS로 문자 설정해 분리 가능
[root@sooyeon 0727]# for test in $(cat /etc/passwd | grep user1)
> do echo $test; done
user1:x:1000:1000:user1:/home/user1:/bin/bash
[root@sooyeon 0727]# set | grep IFS
IFS=$' \t\n'
[root@sooyeon 0727]# IFS=:
[root@sooyeon 0727]# set | grep IFS
IFS=:
[root@sooyeon 0727]# for test in $(cat /etc/passwd | grep user1); do echo $test; done
user1
x
1000
1000
user1
/home/user1
/bin/bash

전체 인스턴스 관리 명령어 만들어 보기

  1. 2개의 인스턴스 생성 후 확인

    virsh list --all # 만약 --all 이 빠지면 중지중인 인스턴스는 확인되지 않음
    [root@sooyeon cloud]# virsh list --all | grep -v Id
    ----------------------------------------------------
     7     test1                          running
     8     1                              running
    
    # 이름만 뽑기
    [root@sooyeon cloud]# virsh list --all | grep -v Id | gawk '{print $2}'
    
    test1
    1

    v : 해당 단어 제외

    file 이름 : allvm을 만들고

    allvm start 하면 모든 인스턴스가 실행 (virsh start test1)

    allvm destory 하면 모든 인스턴스가 종료됨 (virsh destroy test1)

    allvm undefine 하면 모든 인스턴스가 삭제됨 (단, 디스크는 남아있도록) (virsh undefine test1)

    종료되면 Id가 -가 되기때문에 이름으로 제어하면 됨

    allvm → $PATH

    touch /usr/bin/allvm
    chmod +x /usr/bin/allvm
    [root@gildong 0726]# cat /usr/bin/allvm
    #!/bin/bash
    
    for vm in $(virsh list --all | grep -v ID | gawk '{print $2}')
    do
            virsh $1 $vm
    done
    
    case $1 in
    start)
            echo "모든 인스턴스가 실행되었습니다";;
    destroy)
            echo "모든 인스턴스가 종료되었습니다";;
    undefine)
            echo "모든 인스턴스가 삭제되었습니다";;
    *)
            echo "알수없는 명령어";;
    esac
    

for문을 C 스타일로 사용하기

[root@sooyeon 0727]# for (( i=1; i<=10; i++ ))
> do echo $i ; done
1
2
3
4
5
6
7
8
9
10

while

  • 조건에 참이라면 계속해서 반복
  • 1외에 다른 숫자나 문자도 참으로 됨 0도 참으로 됨
  • 아예 쓰지 않거나 ‘’로 하면 거짓으로 됨
# 종료되지 않고 계속 출력
while [ 1 ]
do
	echo "이것이 리눅스다."
done
exit 0

우리는 메뉴 생성 시 종료 없이 메뉴의 내용을 출력하고자 하는 경우 주로 사용한다.

  • while문 활용
#!/bin/bash

var1=10

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

[root@sooyeon 0727]# ./test1.sh
10
9
8
7
6
5
4
3
2
1
  • 인스턴스의 이름을 순서대로 반복 지정

예) 인스턴스의 이름 ? test → $name

개수 ? 3 → $num

test-1

test-2

test-3

for (( i=1; i<=$num; i++ ))
	do
		virt-install --name ${name}-${i} ...
	done
echo "인스턴스 $i개가 생성되었습니다."
  • while문으로 비밀번호 맞을 때 까지 받도록 하기
[root@sooyeon 0727]# cat test1.sh
#!/bin/bash

read -s -p "비밀번호 : " pass
echo
while [ $pass != "1234" ]
do
        echo "잘못된 패스워드"
        read -s -p "비밀번호 : " pass
        echo
done
echo "로그인 성공"

[root@sooyeon 0727]# ./test1.sh
비밀번호 :
잘못된 패스워드
비밀번호 :
로그인 성공

read -s : secure로 비밀번호를 입력할 때 입력하는 텍스트가 보이지 않게 하도록 함

until문

  • while과 반대로 동작으로 조건식이 참일때까지(=거짓인 동안) 계속 반복
[root@sooyeon 0727]# cat test2.sh
#!/bin/bash

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

[root@sooyeon 0727]# ./test2.sh
100
75
50
25

select 명령과 메뉴

  • 반복문의 한 종류로 주로 메뉴 생성에 사용된다.
select 변수명 in 리스트
do
	명령 or 변수
done

사용자로부터 값을 받기 위해서는 프롬프트가 필요

PS1

  • 일반 쉘에서 명령 입력 행
  • [root@loaclhost ~ ]#

PS2

[root@sooyeon bin]# echo "hello
> "
hello

PS3

  • 메뉴를 출력하고 메뉴에서 선택하도록 프롬프트를 띄운다.
  1. hello
  2. hi
  3. nice to meet you

번호를 선택하세요 :

[root@sooyeon 0727]# ./test3.sh
1) ls -l
2) date
3) pwd
4) exit
실행하고 싶은 명령을 선택하세요 : 1
total 20
-rwxr-xr-x 1 root root 1068 Jul 27 09:12 cvm.sh
-rw-r--r-- 1 root root   68 Jul 27 10:14 db.txt
-rwxr-xr-x 1 root root  183 Jul 27 10:48 test1.sh
-rwxr-xr-x 1 root root   86 Jul 27 10:52 test2.sh
-rwxr-xr-x 1 root root  154 Jul 27 11:15 test3.sh
실행하고 싶은 명령을 선택하세요 : 2
Wed Jul 27 11:16:00 KST 2022
실행하고 싶은 명령을 선택하세요 : 3
/root/0727
실행하고 싶은 명령을 선택하세요 : 4

이렇게 되면 명령어 그대로가 출력됨

예를들어 1) 현재 디렉토리 출력하기 이런식으로 하고싶음

select를 단독으로 사용하면 명령을 그대로 나열해야 하므로 case와 함께 사용하면 효율적이다.

case $var in

메뉴1)

ls -l

이런식으로 활용 가능하다.

[root@sooyeon 0727]# cat test4.sh
#!/bin/bash

PS3="실행하고 싶은 명령을 선택하세요 : "

# 'ls -l' -> date -> pwd -> exit
select comm in "디렉토리파일확인" "날짜확인" "위치확인" "종료"
do
        case $comm in
        디렉토리파일확인)
                ls -l ;;
        날짜확인)
                date ;;
        위치확인)
                pwd ;;
        종료)
                exit ;;
        *)
                echo "잘못된 번호를 선택했습니다.";;
        esac
done
[root@sooyeon 0727]# ./test4.sh
1) 디렉토리파일확인  3) 위치확인
2) 날짜확인          4) 종료
실행하고 싶은 명령을 선택하세요 : 1
total 24
-rwxr-xr-x 1 root root 1068 Jul 27 09:12 cvm.sh
-rw-r--r-- 1 root root   68 Jul 27 10:14 db.txt
-rwxr-xr-x 1 root root  183 Jul 27 10:48 test1.sh
-rwxr-xr-x 1 root root   86 Jul 27 10:52 test2.sh
-rwxr-xr-x 1 root root  154 Jul 27 11:19 test3.sh
-rwxr-xr-x 1 root root  375 Jul 27 11:22 test4.sh
실행하고 싶은 명령을 선택하세요 : ㅇdf
잘못된 번호를 선택했습니다.
실행하고 싶은 명령을 선택하세요 : 4

Quiz

원격지와의 통신 상태를 확인하기 위해 우리는 ping을 사용할 예정이다.

www.google.com, www.naver.com, www.daum.net 으로 ping을 보내기 위한 프로그램을 select와 case를 이용하여 구현해보기

1) 구글 2)네이버

3) 다음

과 같이 나오게 하기

[root@sooyeon 0727]# cat test5.sh
#!/bin/bash

PS3="통신 확인 할 주소를 선택하세요 : "

select comm in "구글" "네이버" "페이스북" "종료"
do
        case $comm in
        구글)
                ping www.google.com -c 3 ;;
        네이버)
                ping www.naver.com -c 3 ;;
        페이스북)
                ping www.facebook.com -c 3 ;;
        종료)
                exit ;;
        *)
                echo "잘못된 번호를 선택했습니다.";;
        esac
done

[root@sooyeon 0727]# ./test5.sh
1) 구글
2) 네이버
3) 페이스북
4) 종료
통신 확인 할 주소를 선택하세요 : 3
PING star-mini.c10r.facebook.com (157.240.215.35) 56(84) bytes of data.
64 bytes from edge-star-mini-shv-01-ssn1.facebook.com (157.240.215.35): icmp_seq=1 ttl=52 time=2.05 ms
64 bytes from edge-star-mini-shv-01-ssn1.facebook.com (157.240.215.35): icmp_seq=2 ttl=52 time=2.20 ms
64 bytes from edge-star-mini-shv-01-ssn1.facebook.com (157.240.215.35): icmp_seq=3 ttl=52 time=39.7 ms

--- star-mini.c10r.facebook.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 6056ms
rtt min/avg/max/mdev = 2.051/14.652/39.703/17.713 ms
통신 확인 할 주소를 선택하세요 : 4

break/continue

  • 반복문 내에서 반복을 강제로 종료하고 프로그램을 종료하고자 한다면 break를 사용할 수 있고, 아래의 내용을 더이상진행하지 않고 상단으로 이동하려면 continue를 사용할 수 있다.

break 2는 바깥쪽 루프를 종료한다는 뜻. (바로 안쪽이 loop1, 그 다음 바깥이 loop2)

break는 내가 있는 안쪾 루프를 종료한다는 뜻.

  • break
[root@sooyeon 0727]# cat break1.sh
#!/bin/bash

for (( a=1; a < 4; a++ ))
do
        echo "OUTER : $a"

        for (( b=1; b < 100; b++ ))
        do
                if [ $b -eq 5 ]
                then
                        break
                fi
                echo "   INNER : $b"
        done
done

[root@sooyeon 0727]# ./break1.sh
OUTER : 1
   INNER : 1
   INNER : 2
   INNER : 3
   INNER : 4
OUTER : 2
   INNER : 1
   INNER : 2
   INNER : 3
   INNER : 4
OUTER : 3
   INNER : 1
   INNER : 2
   INNER : 3
   INNER : 4
  • break2
[root@sooyeon 0727]# cat break2.sh
#!/bin/bash
for (( a=1; a < 4; a++ ))
do
        echo "OUTER : $a"

        for (( b=1; b < 100; b++ ))
        do
                if [ $b -gt 4 ]
                then
                        break 2
                fi
                echo "   INNER : $b"
        done
done
[root@sooyeon 0727]# ./break2.sh
OUTER : 1
   INNER : 1
   INNER : 2
   INNER : 3
   INNER : 4
  • continue
[root@sooyeon 0727]# cat continue1.sh
#!/bin/bash

for (( i=1; i<15; i++ ))
do
        if [ $i -gt 5 ] && [ $i -lt 10 ]
        then
                continue
        fi

        echo "num : $i"
done

[root@sooyeon 0727]# ./continue1.sh
num : 1
num : 2
num : 3
num : 4
num : 5
num : 10
num : 11
num : 12
num : 13
num : 14

0개의 댓글