본문 바로가기

별걸다하는 IT/리눅스 유닉스

[리눅스 / 유닉스 / 셸 프로그래밍 ] 반복문 for문 루프(loop)! 문법, 활용예제, 같이 쓰면 좋은 구문, break, continue

[ Linux / Unix / Shell programming INDEX ]

안녕하세요~~ㅎㅎ

오늘은 반복문 중 for문에 대해서 포스팅을 이어가보도록 하겠습니다.

 

▼참고

배시 말고 일반 프로그래밍(C, C++ JAVA)에서 for문의 포스팅

[C, C++, Java 등 언어 공통] 반복문 상세설명!(for, do while, 향상된 for문 사용법, 차이점 및 실행 순서)

 

[C, C++, Java 등 언어 공통] 반복문 상세설명!(for, do while, 향상된 for문 사용법, 차이점 및 실행 순서)

[C언어, C++언어 완전정복 목차 링크!] 문득 그런 날이 있지 않나요? 아무것도 하기 싫은날~~~ㅎㅎㅎㅎㅎ 그렇다고 가만히 있자니 시간이 아깝구 블로그 포스팅을 씁니다. ㅎㅎㅎㅎ 참고로 자바나 C언어나 C++이..

jhnyang.tistory.com

코드에서 빠질 수 없는 구문이라 하면 당연 반복문이겠죠?

특히 자동화 스크립트를 많이 짜는 셸에서는 반복문 활용도가 높습니다.

특정 명령을 규칙에 따라 자동적으로 수행해주는 반복문~ 그 중에서도 오늘은 for문에 대해서 진행할게요!

 

반복문 for 기본 문법

for 변수 in [범위](리스트 또는 배열, 묶음 등) do 반복할 작업 done

for 변수 in [범위](리스트 또는 배열, 묶음 등)
do
   반복할 작업 
done

in뒤에 나오는 묶음의 개수만큼 반복이 진행되겠죠?

in뒤에는 그니까 복수가 나오는 데, 쪼개질 수 있는 리스트나, 배열, 명령어의 결과 묶음 등 다양한 것(?)들을 넣어서 활용할 수 있어요 ㅎㅎ 

하나씩 순차적으로 빼서 변수에 저장하고 do ~done사이에 있는 작업을 진행합니다.

어떤 디렉터리에 있는 파일들을 하나하나씩 추출해서 반복적으로 특정작업을 하게 할 수도 있고~

특정 횟수만큼 작업을 반복시킬 수도 있고 ~

반복적으로 설정 파일들을 읽어서 실행시킬 수도 있고

활용은 무궁무진합니다 반복문이니까요!! 무엇인들 못하리~

다양한 반복문 문법과 활용법들

▶1. 기본 문법

#!/bin/bash
for var in 1 2 3 4 5
do 
  echo var value :$var
done

1번 결과창

컴마로 1,2,3,4,5 이렇게 하지 않으니 주의~

셸 스크립트는 배열 선언할 때도 원소마다 컴마를 쓰지 않고 띄어쓰기로 구분하죠 ㅎㅎ in뒤에 나오는 값들도 마찬가지입니다. 자 1 2 3 4 5 다섯개의 숫자 리스트가 in뒤에 주어졌어요 var에는 1 2 3 4 5 값이 순차적으로 들어가면서 총 5번 반복됩니다.

기본 문법이라 bash에서도 ksh에서도 대부분의 셸에서 수행 가능해요

하지만 여지껏 포스팅을 보면서 느꼈겠지만, for문 또한 앞으로 나올 문법 중에서는 지원하는 셸도 있지만 지원되지 않는 셸도 있으니 잘 확인하기!

▶2. in 리스트(list)

#case 1
list="1 2 3 4 5"
for var in $list
do 
  echo var value :$var
done

#case 2
for var2 in "1 2 3 4 5"
do 
  echo var2 value :$var2
done

분명 같아 보이지만 달라요 ㅎㅎ 주의해야할 점은 in뒤에 따옴표로 저렇게 case 2처럼 넣어주면, 5개가 아니라 하나의 문자열로 간주해버려서 값이 다르게 나옵니다 

2번 결과창

이유는 문자열조각내기(?) 라는 word spliting기능 때문인데요~! 자세한 것은 "문자열 조각 Word Spliting" 포스팅을 참고해주세요 :)

▶3. 파일 출력하기

for file in /etc/*
do 
  echo ${file}
done

이렇게 뒤에 와일드카드를 이용한 파일리스트를 in뒤에 지정해줄수도 있어요

그러면 /etc/에 있는 모든 파일들을 하나하나 반복문을 돌면서 접근하게 됩니다.

결과 개수가 너무 많아서 head 명령어를 이용해서 맨 처음 10개 리스트만 출력해줬어요 ㅎㅎ

▶4. 순차적으로 증가하면서 반복 (괄호로 범위 지정)

{START..END}

#!/bin/bash
for var in {1..5}
do 
  echo var value :$var
done

점이 세개가 아니고 두 개 입니다! 세개로 찍으면 안돼용~

결과는 [1번결과창]과 동일하게 나옵니다. bash는 3.0이전 버전은 지원되지 않습니다.

유닉스AIX 운영체제 ksh 셸에서 테스트

괄호로 범위지정하는 게 먹히지 않으면 {1..5}를 하나의 문자열로 보고 위와 같이 출력됩니다.

▶5. 일정 간격만큼 증가시키면서 반복 (괄호)

{START..END..INCREMENT}

for var in {1..10..2}
do
  echo var value :$var
done

bash 4.0버전부터는 괄호로 범위지정에서 간격까지 지정해줄 수 있습니다. 하나씩 순차가 아니라 2개씩 건너뛸 수 있어요

5번 결과창

▶6. 순차적으로 증가하면서 반복 (seq)

seq 명령어는 저 위에 괄호문법이 없었을 시절, 즉 3.0버전 이전에 사용하던 방식입니다.

sequence 시퀀스의 약자예요 ㅎㅎ

만약 너무 옛날 버전이 아니라면, 저 괄호방식을 사용하는게 더 좋고 이건 구식(?)이라 권장되지 않습니다. 

어느 환경에서 내가 작업하게 될 지 모르니 알아놓는 것은 당근 좋겠죠!

(유닉스에서는 안되는 경우가 많습니당 )

for var in $(seq 5)
do 
   echo var value :$var
done

실행 후 출력은 1번 결과창과 동일합니다 ㅎㅎ

$()는 명령 실행을 의미하고 'seq n'는 1부터 n까지 순차적으로 출력해 줘요 ㅎㅎ

for var in `seq 0 5` ; do
  echo var value :$var
done

6번 결과창

``(역따옴표)는 $()와 같은 역할로 명령을 실행합니다.

seq n은 1부터 n까지였지만, 인자를 두 개를 붙임으로써 시작지점을 지정할 수 있어요 ( seq START END )

시작지점을 0으로 지정해서 5까지 출력해보았습니다

▶7. 일정 간격만큼 증가시키면서 반복 (seq)

for var in `seq 1 2 10`
do 
  echo var value :$var
done

이렇게 하면 5번 결과창과 동일한 출력을 얻습니다. 1번부터 2씩 건너뛰면서 10이 넘지 않을때까지 수행하라는거죠~ 1, 3, 5, 7 9 요렇게 var에 차례로 대입되겠네요 ㅎㅎ

얘도 역시 UNIX의 AIX 운영체제 ksh에서는 seq 명령어를 찾을 수 없음! 이렇게 나오네요 ㅎㅎ

▶8. in 배열

ary=(1 2 3 4 5)
for var in "${ary[@]}"
do 
   echo var value :$var
done

ary[@]부문은 ary[*]와 스위칭 가능합니다 (둘 다 똑같은 의미)

IBM 유닉스 운영체제 AIX에서는 배열 선언 방식이 달라요 ㅎㅎ (자세한 건 배열 포스팅에서)

배열 선언 방식 차이는 있을 수 있지만, 이렇게 반복문에서 범위로 넣어서 loop를 돌려줄 수 있다는 거~!

결과창은 1번 결과창과 동일합니다.

▶9. 이중괄호 (( )) double parentheses

for ((i=0; i<5; i++)); do
  echo $i
done

그나마 우리가 익숙한 C, JAVA와 비슷한 구문~!

이 이중괄호는 산술연산을 가능하게 확장해줘서 우리가 익숙한 프로그래밍 언어를 사용할 때 처럼 사용가능하게 해줍니다. ㅎㅎ 예전부터 지원했던 기능이 아니기 때문에 최신 버전이 아니거나 오래된 유닉스 서버를 사용하고 계시면 지원안될 수 있습니다.

8번 결과창

5보다 작을때까지니까 4까지 출력함!

▶10. 무한루프도 물론 가능

for (( ; ; ))
do 
  echo "infinite loops, hit CTRL+C to stop"
done

근데 당연히 무한루프가 걸릴 수 있는 가능성이 있다면, 이를 컨트롤해줄 break문과 continue가 있어야겠죠?

셸 프로그래밍에도 해당 명령어가 있습니다 ㅎㅎ

강제종료로 도중에 빠져나오려면 CTRL+C를 누르면 돼요 ㅎㅎ

▶11. break문과 continue!

for file in /etc/*
do
  if [ "${file}" == "/etc/shadow" ]; then
     echo yes
     break
   fi
done

3번 예문을 토대로 break문을 넣어봤어요 ㅎㅎ

파일을 검색하다가 만약 "/etc/shadow"파일을 찾으면, yes를 출력하고 반복문을 빠져나오게 처리를 했습니다!

break는 조건을 충족하면 반복문을 빠져나오고,

continue는 조건을 충족하면 그 아래문장을 수행하지 않고 위로 올라가서 다시 한 번 더 반복을 수행해요 ㅎㅎ (나머지는 생략하고 반복조건으로 돌아감)

FILES="$@"
for file in $FILES
do 
   if [ -f ${file}.bak ]; then
     echo "${file}.bak file exists"
     continue
   fi
   cp $file $file.bak
done

만약 파일이 존재하면 그 뒤의 cp명령어를 스킵하고 다음 으로 넘어가요 

▶12. 인자로 받을 수도 있어요

i=1
for var
do 
  echo $var 
done

11번 결과창

리스트를 인자로 줬기 때문에 in이 없습니다. 생략된거죠 ㅎㅎ

i=1
for var in $*; do 
  echo $var 
done

명시를 해주고 싶으면 인자 전체를 의미하는 위치매개변수 $*나 $@를 넣어주면 돼요

▶13. foreach 문!

#!/bin/csh
foreach i ( 1 2 3 )
 echo i value :$i
end

배시나 ksh에서는 아직 지원하지 않지만 csh에서는 지원하는 foreach문도 있습니다.

 

▶14. 산술연산과 조합하기 좋아요 ( let, expr )등

프로그래밍에서도 조건이 맞으면 반복문을 빠져나오게 조절하기 위해서, 또는 무한루프에 안걸리게 하기 위해서, 

변수를 하나씩 증가시켜준다던가 산술연산을 많이쓰죠?

셸 스크립트에서도 이를 가능하게 해주는 let, expr등과 자주 사용됩니다

let 또는 expr은 문자열타입밖에 없는 셸 변수들로 산술연산을 할 수 있도록 도와주는 명령어들이예요

loop_cnt=0
for file in *  #현재 디렉터리 모든 파일
do 
   let loop_cnt+=1  #반복문이 돌때마다 1씩 더함
   echo $loop_cnt file: $file
done

14번 결과창

▶15. in 뒤에 명령어 실행 결과를 붙여도 된다.

이미 앞의 예제들에서 눈치를 채셨겠지만, in뒤에 리스트들로 명령어 실행을 넣어서 치환할 수 있어요 

명령어를 실행시키는 문법으로는 백슬래시랑 $()가 있습니다.

 

먼저 연습문제로 과일들이 적힌 하나의 파일을 작성해줍시다.

apple banana orange grape

 

이렇게, fruit_list.txt파일을 하나 만들어서 적어줬어요 

for fruit in $(cat fruit_list.txt)
do
  echo current fruit: $fruit
done

그리고 스크립트 파일은 위처럼 적은 후 실행시키면, 

15번 결과창

잘 들어간 것을 확인할 수 있습니다

▶16. 띄어쓰기가 아니라 컴마일때,,

이건 for문 반복문에 오로지 연관이 있다 하긴 어려운데 그냥 조금 더 나아가서 끄적여 보면

보통 설정파일이나 이런 것들을 읽어서 처리할 때가 많은데 , 띄어쓰기만으로 구분이 안되어 있을 수도 있겠죠..

var=a,b,c
for i in ${var//,/ }
do 
  echo $i
done

"문자열 확장, 치환 포스팅"에서 배웠던, 컴마를 공백으로 변경시켜서 처리할 수도 있습니당

모든지 활용은 자기 하기 나름~

16번 결과창

▶17. for문 표준입력, 표준출력 재지향

for name in `seq $line_count`
do
  read name
  echo "$name"
  if [ "$name" = "$FinalName" ]
  then
    break
  fi  
done < "$Filename" > "$Savefile"  

리다이렉션 <. >를 활용해서, 읽을 파일이랑, 출력 파일을 지정해줄 수 있는거예요

read는 입력을 받는건데, '<'를 이용해서 Filename변수에 저장된 파일로부터 단어를 읽어 name에다가 저장하는걸 반복한다는 코드입니다.중간에 조건문과 break를 통해서 마지막 파일명과 일치하면, 반복문을 빠져나오도록 했네요! 

'<'와 반대로, '<'를 사용해서 echo와 같은 출력함수를, 출력파일에다가 남길 수 있도록 입출력 파일들을 지정해주고 있어요 ㅎㅎ

 

정말 다양한 방법들이 많죠!? ㅎㅎ

좀 알아두면 좋을 표현들을 정리해봤어요!

도움이 되셨다면 가기 전, 덧글, 광고보답 공감 헿~~ 오타지적과 질문 좋아요

오늘도 수고하셨습니다 여러분 다음 포스팅에서 뵈어요!!