블로그 이미지
OSSW(Open Source System SoftWare

calendar

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        

Notice

지난 글에 이어서 이번에는 sed를 이용하여 new line을 특정 문자열로 변경하는 방법에 대해 말씀 드리도록 하겠습니다.

 

(2) new line --> 특정 문자열


# cat test.txt

11111

22222

33333

44444

55555



위와 같은 컨텐츠를 가진 txt 파일이 있다고 가정합니다.

 

위 컨텐츠에서 Enter가 적용된 부분(new line)을 ':'(colon)으로 변경하고자 한다면 다음과 같이 수행합니다.


# sed 'N;N;N;N;s/\n/:/g' test.txt



sed 명령에서 'N' 옵션은 줄바꿈문자(\n)를 /A패턴/ 공간에 더하고 입력의 다음 줄을 읽어 패턴 스페이스에 덧붙이겠다는 뜻입니다.

 

무슨 말인지 이해가 잘 되시나요?

 

사실 저는 아직도 완전히 이해가 되지는 않습니다.;;;;

 

문제 해결방안을 찾다보니 아래와 같이 한글로 된 URL을 찾았는데 그 글을 올리신 분이 정의해 놓은 것을 그냥 가져다 적은 것입니다.

(출처: http://wiki.kldp.org/Translations/html/Sed-KLDP/sedprograms.html#OVERVIEWOFREGULAREXPRESSIONSYNTAX)

 

아무튼 특정 문자열로 변경해야할 new line의 수만큼 'N' 옵션을 써주시면 되는데요.

 

이 옵션 사용 후 /A패턴/ 에 해당하는 부분에 개행문자인 '\n' 을 입력해 주시고 /B패턴/ 에 new line 대신 들어갈 문자열을 입력해 주시면 됩니다.

 

이렇게 하는 것이 제가 sed를 이용해서 new line을 특정 문자열로 변경하는 방법이라고 알아낸 것인데요.

 

한 가지 단점이..

 

위와 같은 예제에서 new line의 개수가 정확히 몇 개인지 확인이 가능하다면 모르겠지만, 개수 파악이 안되는 컨텐츠의 경우 어떻게 해야 할지 아직 찾지 못했습니다.;;;;

 

물론 'tr' 명령어를 사용하여 다음과 같이 구현해도 되긴 합니다.


cat test.out | tr "\n" ":" | cut -d ':' -f 1-5



하지만, 위 방법 역시도 '|'(pipe) 를 이용한 명령어의 길이가 길어지기도 하고 cut 명령 뒤에 '-f' 옵션으로 출력 컬럼을 정할 때에도 ':'(colon) 개수를 알아야만 한다는 단점이 있습니다.

posted by 박현명

이번 글은 sed 명령어를 이용하여 new line(개행문자 \n)을 특정 문자열로 바꾸거나, 특정 문자열을 new line으로 변경하는 방법에 대한 글입니다.

 

Shell Script를 작성하다 보면 한꺼번에 많은 내용을 바꾸어야 할 때가 종종 발생하는데, 그 때 유용하게 쓰이는 명령어가 바로 이 'sed' 명령어죠.

 

sed와 비슷한 역할을 하는 명령어로 'tr' 이라는 명령어도 있습니다.

 

각자가 처한 상황에 맞게, 취향에 따라 골라 쓰시면 되는데요.

 

그러한 내용 변경 상황 중에서도 new line, 다시 말해 줄바꿈 상태를 특정 문자열로 변경하거나, 그 반대로 특정 문자열을 줄바꿈 상태로 바꿔야 하는 경우가 있습니다.

 

그럴 때 다음과 같이 사용하시면 되겠습니다.

 

(1) 특정 문자열 --> new line


# cat test.txt

11111,22222,33333,44444,55555



위와 같은 문자열들로 이루어진 txt 파일이 있다고 가정합니다.

 

위 컨텐츠 중, ','(comma)를 new line으로 바꾸고자 한다면 다음과 같이 수행합니다.


# sed 's/,/\

> /g' test.txt > test1.txt



sed 명령에서 's' 옵션은 'switch' 를 뜻하는 옵션으로 뒤에 나오는 /A패턴/을 /B패턴/으로 바꾸겠다는 뜻입니다.

 

제일 뒤의 'g' 옵션은 'global' 을 뜻하는 옵션으로 /A패턴/이 여러 개일 경우 전부 바꾸겠다는 뜻이죠.

 

이 옵션을 주지 않으면 제일 첫 번째에 나타나는 /A패턴/ 한 개 문자열만 바뀌게 됩니다.

 

위 예시에서는 /A패턴/ 자리에 바뀌어야할 기존 문자열인 ','(comma) 를 입력하였습니다.

 

/B패턴/ 자리에 new line 을 뜻하는 문자열 입력을 위해 '\'(back slash)를 입력한 후 실제 Enter 버튼을 눌러 줄바꿈을 해줍니다.

 

UNIX나 LINUX 의 프롬프트 상에서 위 명령을 실행할 경우, 줄이 바뀌었다는 표시인 '>'(redirection) 기호가 나타납니다.

 

그러면 나머지 global 옵션이라든가, 파일 이름 등을 나열해 줍니다.

 

핵심은 '\'(back slash)와 Enter key 누름이 되는 것이구요.

 

Shell Script 상에서는 '>'(redirection) 표시가 되지 않을 것이기에 Enter 버튼을 누른 후 나머지 구문을 완성해 주시면 됩니다.

 

이 때 한 가지 주의하실 것은 Shell Script 작성을 보기 좋게 하고자 tab 키나 space 키로 들여쓰기를 하는 경우가 있는데, 위와 같이 특정 문자열을 new line으로 바꾸는 sed 문장을 작성하실 경우, Enter key 누름 효과 이후에 tab 키나 space 키를 적용하면 안됩니다.


sed 's/,/\

    > /g' test.txt > test1.txt   --> (X)

----

└> space 적용 부분

 

sed 's/,/\

> /g' test.txt > test1.txt       --> (O)



위와 같이 정상적으로 sed 명령이 수행되었다면 다음과 같은 결과가 나타나게 되겠죠.


# cat test1.txt

11111

22222

33333

44444

55555



이상 특정 문자열을 new line으로 변경하는 방법에 대해 말씀 드렸구요.

 

다음 글에서는 그 반대인 new line을 특정 문자열로 변경하는 방법에 대해서 말씀 드리도록 하겠습니다.

posted by 박현명

5. case문

 

(1) 기본 사용법 및 예제 


case 변수 in

     경우1)

             ~

             ;;

     경우2)

             ~

             ;;

     경우3)

             ~

             ;;

             ...

esac


case문의 사용법은 아주 간단합니다.

 

shell script를 아무 생각없이 코딩하다 보면 무수히 많은 if문을 남발하게 되고 소스 자체가 지저분해 보이게 되는데 이 때 이 case문만 적절히 사용할 줄 알아도 훨씬 심플하고 보기 좋은 shell script를 작성할 수 있습니다.

 

그럼 바로 예제문을 통해 설명 드리겠습니다.

 

먼저 동일한 결과를 보여주는 if문부터 보도록 하겠습니다.


tmpSize=`df -g /tmp | grep tmp | awk '{print $3}' | cut -d '.' -f 1`
echo 'The size of /tmp filesystem '${tmpSize}' GB'

 

if [ ${tmpSize} -eq 0 ]; then

    chfs -a size=+2G /tmp

    echo 'The size of /tmp filesystem is increased 2GB.'

elif [ ${tmpSize} -eq 1 ]; then

    chfs -a size=+1G /tmp

    echo 'The size of /tmp filesystem is increased 1GB.'

else

    echo 'The size of /tmp filesystem is equal or greater than 2GB.'

fi


예문이 짧아서 if문이나 case문이나 별차이 없어 보이기도 합니다만, 그래도 아래 case문이 더 깔끔해 보이지 않나요?;;;; 

 tmpSize=`df -g /tmp | grep tmp | awk '{print $3}' | cut -d '.' -f 1`
  echo 'The size of /tmp filesystem '${tmpSize}' GB'
  
  case ${tmpSize} in
     0)
        chfs -a size=+2G /tmp
        echo 'The size of /tmp filesystem is increased 2GB.'
        ;;
     1)
        chfs -a size=+1G /tmp
        echo 'The size of /tmp filesystem is increased 1GB.'
        ;;
     *)
        echo 'The size of /tmp filesystem is equal or greater than 2GB.'
        ;;

  esac


위 예제는 AIX에서 /tmp 파일시스템의 사용 가능 용량(free size)에 비추어 파일시스템 크기를 2GB 이상으로 늘려주려는 case문 예제입니다.

 

먼저 첫 번째줄의 명령 구문은 /tmp 파일시스템의 정보를 GB 단위로 가져온 후(df -g /tmp), 제일 윗 줄의 불필요한 row 부분을 제거하고(grep tmp), 세 번째 컬럼인 Free size 정보만 뽑아낸 다음(awk '{print $3}'), 소수점 이하 자리는 제외하고 정수 부분의 값만 가져오겠다(cut -d '.' -f 1)는 뜻입니다.


<참조 - AIX 에서의 df 명령 실행 결과 화면>



위 화면과 같은 상황에서 첫 번째 명령구문을 실행하였다면 output으로 '1'을 반환하겠죠?

 

그렇다면 case문의 ${tmpSize} 변수값에 '1'이 넘어갈 것이고 변수가 '1'일 경우에 실행되는 구문인 'chfs -a size=+1G /tmp' 가 실행될 것입니다.

 

case문에 보이는 '*'(asterisk) 같은 경우는 if문의 else와 같은 용도라고 보시면 되는데요.

 

위 예제에 비추어 설명 드리자면, ${tmpSize} 변수값이 0도 아니고 1도 아닐 경우엔 별다른 명령문 수행없이 echo문만 수행하겠다는 내용이지요.

 

아주 간단하죠?

 

이상 case문에 대한 기본 사용법 및 예제에 대해서 말씀 드렸습니다.


posted by 박현명

4. while문

 

(1) 기본 사용법 및 예제 


while [ 조건식 ]; do       // while문 시작

    ~

done                            // while문 종료



for문과 마찬가지로 while문 또한 루프 처리를 담당합니다.

 

사용법이 다소 다르므로 상황에 따라 적절히 선택해서 사용해야 하는데요.

 

이 while문 역시 조건식 뒤에 세미콜론을 사용하지 않고 사용 가능합니다.

 

while문의 조건식엔 보통 산술 비교 형태가 들어갑니다.

 

가령, 다음과 같은 식이지요.


while [ ${index} -le 10 ]      // index 변수값이 10보다 작거나 같은 동안 while문 수행

do

   ~

done



위와 같은 조건식으로 시작하여 '~' 로 처리한 컨텐츠 부분에 그 조건식에 위배되는 순간이 오게 되면 while문을 종료하는 식이지요.

 

헌데 for문이든 while문이든 아주 중요한 것이 있습니다.

 

아실 만한 분들은 다 아시겠지만 바로 무한루프에 빠지는 경우를 방지해야 한다는 건데요.

 

이런 무한루프 방지를 위해 continue 나 break 문을 적절하게 사용해야 합니다.

 

또한, 내가 원하는 결과값을 이미 얻었음에도 불구하고 while문을 계속 수행해야할 필요는 없겠죠?

 

그렇게 되면 불필요하게 시스템의 리소스를 잡아먹게 되고 성능이 느려지게 됩니다.

 

바로 그럴 때 break 나 continue 문을 사용하는 건데요.

 

다음 예제를 한 번 보시죠.


index=1

 

while [ ${index} -le 1000 ]; do    // index 값이 1000보다 작을 때까지 while문 수행

 

    if [ ${index} -eq 10 ]; then       // index 값이 10과 같으면

        age=$((index + 20))            // age 변수에 (index 값 + 20)의 결과값을 할당

    fi

    index=$((index + 1))               // index 값 1 증분

 

done

 

echo 'I am '${age}' years old.'



위 예제를 보시면 결국 내가 원하는 값은 제일 마지막 줄에 echo 커맨드를 통하여 age 값을 포함한 한 문장을 출력하는 것이란 걸 알 수 있습니다.

 

허나, break 문이 존재하지 않기 때문에 index에 10이 할당되고 난 이후에도 while문을 계속 수행할 수밖에 없는 구조로 되어 있습니다.

 

이럴 때 다음과 같이 break 문을 사용하면 시스템 부하도 줄일 수 있고 응답 시간도 줄일 수 있습니다.


index=1

while [ ${index} -le 1000 ]; do    // index 값이 1000보다 작을 때까지 while문 수행

     if [ ${index} -eq 10 ]; then     // index 값이 10과 같으면

         age=$((index + 20))          // age 변수에 (index 값 + 20)의 결과값을 할당

         break                               // 원하는 값을 얻었으므로 while문을 빠져나감 

     fi

     index=$((index + 1))             // index 값 1 증분

done

echo 'I am '${age}' years old.'



위와 같이 for문이든 while문이든 루프 제어문에서 break 나 continue 를 적절히 사용해 주시면, 무한루프도 방지할 수 있고 시스템 부하도 줄일 수 있습니다.(일종의 shell script 튜닝 포인트죠.)

 

이상 while문에 대한 기본 사용법 및 예제였습니다.

posted by 박현명

#!/bin/sh

if [ -d $1 ]; then

        cd $1


        if [ -f $2 -a -s $2 ]; then


                echo $2' is file and has contents more than one character.'

 

                array=`cat $1/$2`

 

                for day in ${array}; do

                    if [ -n ${day} ]; then

                        if [ ${day} == "Fri" -o ${day} == "Sat" ]; then

                            echo ${day}' is very happy day!!'
                        else
                            echo ${day}' is gloomy day.'

                        fi
                    fi

                done


        else
                echo $2' is not file or has zero character.'
        fi

fi


앞서 if문 예제 글에서 보여 드렸던 예제 스크립트보단 짧은 스크립트이지만 설명의 편의를 위해 크게 if문과 for문으로 나누어 설명 드리도록 하겠습니다.


 

1) 첫 번째 섹션 - if문 


if [ -d $1 ]; then                             // 첫 번째 매개변수 값이 디렉토리라면,

        cd $1                                     // 해당 디렉토리로 이동


        if [ -f $2 -a -s $2 ]; then        // 두 번째 매개변수 값이 파일(-f)이고 그 파일이 내용을 가지고 있다면(-s),


                echo $2' is file and has contents more than one character.'

 

                array=`cat $1/$2`       // array라는 변수에 두 번째 매개변수인 파일에서 읽어들인 내용을 할당

 

                for day in ${array}; do      // for문 시작

                    ~

                done                                  // for문 종료


        else                     // 두 번째 매개변수 값이 파일이 아니거나 그 파일이 아무런 내용도 가지고 있지 않다면,
                echo $2' is not file or has zero character.'
        fi

fi



라인별 설명은 위 내용을 참조하시면 되겠고,

 

if문의 내용을 한 문장으로 표현하자면,

 

두 번째 매개변수 값이 파일이고 내용을 가지고 있을 경우엔 for문을 실행시켜 원하는 결과를 얻을 것이고, 그렇지 않다면 echo로 그에 대한 내용만 화면에 보여주겠다는 것입니다.

 

if문과 관련해선 앞선 글들에서 자세히 설명해 놓았으니 참고하시면 될 것 같습니다.

 


2) 두 번째 섹션 - for문 


for day in ${array}; do

    if [ -n ${day} ]; then

        if [ ${day} == "Fri" -o ${day} == "Sat" ]; then

            echo ${day}' is very happy day!!'
        else
            echo ${day}' is gloomy day.'

        fi
    fi

done



array라는 변수에 할당된 값이 파일이고 내용을 가지고 있다는 if문을 통과하였다면 for문을 실행하겠죠?

 

그렇다면 이 array 변수를 for문에 집어넣고 이제 띄어쓰기 단위로 구분된 단어 하나하나를 끄집어 내어 day라는 변수에 할당합니다.

 

if문 안의 -n 옵션은 변수의 내용이 null이 아닌지를 판별하는 옵션이므로 day에 할당된 변수값이 null일 경우, 즉 파일의 끝에 도달했을 경우에는 if문을 실행하지 않겠죠.

 

그 다음 if문은 굳이 설명 드리지 않아도 아실 거라 생각됩니다.

 

물론 위 스크립트를 실행시키려면 다음과 같은 샘플 파일이 OS 디렉토리 어딘가에 존재해야만 스크립트 실행 시 매개변수로 넣어줄 수 있겠죠.


# cat /tmp/test.txt

Sun Mon Tue Wen Thu Fri Sat



그리고 다음과 같이 실행시키시면 됩니다.


./ForTest.sh /tmp ForTestResult.txt



이상 for문에 대한 간단한 예제였습니다.


posted by 박현명

3. for문

 

(1) 기본 사용법 


for 단일변수 in 리스트; do    // for문 시작

    ~

done                                  // for문 종료



for문의 용도에 대한 것을 모르시는 분은 없을 겁니다.

 

C, Java 등 많은 language들에서 while문과 함께 가장 많이 쓰이는 루프 처리 구문이 바로 이 for문이기 때문이죠.

 

위 구문에서도 if문 처리에서 보았던 것처럼 세미콜론을 볼 수가 있는데, 마찬가지로 세미콜론을 사용하지 않으려면 다음과 같은 형태로 처리해야 합니다.


for 단일변수 in 리스트      // for문 시작

do

    ~

done                             // for문 종료



'리스트' 자리에는 보통 배열 형태로 들어가게 되는데요.

 

'리스트' 자리의 배열은 일일이 값을 나열할 수도 있고 배열 형태의 값을 가진 파일을 읽어들이는 형태일 수도 있습니다.

 

우선 '리스트'에 일일이 값을 나열하는 방법을 이용한 for문의 예시를 보도록 하겠습니다.


for day in Sun Mon Tue Wen Thu Fri Sat; do

    echo $day

done



위 예제는 '리스트' 자리에 요일 이름을 나열하여 'Sun'부터 'Sat'까지 하나씩 'day'라는 변수에 input값으로 들어가고 echo를 통해 화면에 뿌려지는 예제입니다.

 

그럼 이번에는 '리스트'에 배열 형태의 값을 가진 파일을 읽어들이는 방법을 살펴볼까요?

 

먼저 다음과 같은 값을 가진 파일이 있다고 가정합니다.


# cat test.txt

Sun Mon Tue Wen Thu Fri Sat



그리고 위 파일을 '리스트' 부분에 넣어보겠습니다.


for day in $(cat test.txt); do

    echo $day

done



위 예제는 test.txt 파일의 값을 읽어들여 'day' 변수에 하나씩 input값으로 들어가게끔 하는 것인데요.

 

위 예제처럼 '리스트' 부분에 cat 커맨드를 사용하여 바로 파일을 읽어들일 수도 있고 또는 다음과 같이 사용할 수도 있습니다.


array=`cat test.txt`

 

for day in $array; do

    echo $day

done



`(back quotation)은 어떤 shell command의 실행 결과를 '=(equal)' 좌측의 변수에 할당하고자 할 때 사용합니다.

 

위와 같이 처리하면 앞서 '리스트' 부분에서 바로 cat 커맨드를 사용한 것과 동일한 결과를 가져올 수 있습니다.

 

이상 for문에 대한 기본 사용법 및 간단한 예제들을 살펴보았습니다.

posted by 박현명

(3) 배열

 

배열을 선언하여 값을 할당하는 방법에는 크게 두 가지 정도가 있습니다.

 

하나는 배열의 인덱스 하나하나를 구분하여 각각의 인덱스에 일일이 값을 지정하는 방법과, 또 다른 하나는 뭉탱이로 배열에 값을 넣어주는 방법입니다.

 

먼저 인덱스 하나하나에 값을 따로따로 지정하는 방법은 다음과 같습니다.


array[0]='Shell'

array[1]='Script'

array[2]='Programming'



위 예제의 경우, 인덱스 '0'에는 'Shell'이란 문자열이, 인덱스 '1'에는 'Script'란 문자열이, 인덱스 '2'에는 'Programming'이란 문자열이 각각 지정되었습니다.

 

위와 같이 지정한 후, 다른 라인에서 해당 배열 변수값을 호출하고자 할 때는 아래와 같이 사용하면 됩니다.


echo ${array[0]}

echo ${array[1]}



버퍼에 있는 변수값을 호출하려 할 때, '$'를 붙여서 사용하면 된다는 것은 앞의 글에서 이미 설명 드렸었습니다.

 

헌데, 위 예시에는 그동안 사용하지 않았던 '{ }'(중괄호)가 들어가 있죠?

 

왜일까요?

 

다음과 같은 아주 간단한 스크립트가 있습니다.


 #!/bin/sh  

array[0]='Shell'
array[1]='Script'

 

echo $array[0] $array[1]

echo ${array[0]} ${array[1]}



위 스크립트를 실행시키면 첫 번째 echo 문의 결과값은 'Shell[0] Shell[1]' 이라고 출력되고, 두 번째 echo 문의 결과값은 'Shell Script'라고 출력됩니다.

 

이유인즉슨, '{ }'(중괄호)를 사용하여 array[0], array[1] 등을 하나의 변수로 처리해 주지 않으면, [0], [1] 등을 인식하지 못하고 해당 배열의 첫 번째 인덱스값만 불러오게 되어 있기 때문입니다.

 

꼭 배열을 사용할 때 뿐만 아니라, 많은 경우에서 '{ }'(중괄호)를 필요로 하게 됩니다.

 

'이것은 변수다'라는 것을 명시적으로 표기하여 소스의 가독성을 높이고자 한다면, 변수 호출 시마다 '{ }'(중괄호)를 붙여주는 것이 좋습니다.

 

다음은 뭉탱이로 배열에 값을 할당하여 주는 방법입니다.

 

뭉탱이로 배열에 값을 할당하는 방법도 몇 가지가 있는데, 그 중 사용이 쉽고 자주 쓰이는 두 가지 방식만 살펴보도록 하겠습니다.

 

첫 번째 방식은 다음과 같습니다.


array=(shell script programming)



일일이 값을 할당하는 방식에 비해 훨씬 간결하죠?

 

배열의 인덱스마다 일일이 값을 할당하나, 괄호를 사용하여 한 번에 할당하나 변수 호출의 결과는 같습니다.

 

또 다른 뭉탱이 할당 방식은 파일을 읽어들이는 것입니다.

 

다음 예제를 보시죠.


# cat test.txt

shell script programming

 

array=$(cat test.txt)

echo ${array[0]}



위와 같이 'shell script programming' 이라는 문자열을 담고 있는 파일이 있다면, shell 커맨드인 'cat' 을 이용하여 값을 불러와 배열에 할당할 수 있습니다.

 

Shell Script를 짜다 보면 여러 파일에서 값을 불러와 배열에 저장하고 사용하는 경우가 종종 생기는 데 그 때 위 예제처럼 사용하면 됩니다.

 

그리고 이전에도 한 번 강조했던 내용이지만, 배열 변수에 값을 할당할 때도 '='(equal) 앞뒤로 절대 공백이 존재하면 안된다는 것을 명심하시기 바랍니다.

posted by 박현명

#!/bin/sh

if [ -d $1 ]; then

        cd $1

        ##### Example 1. Test Operator
        if [ -f $2 ]; then
                echo $2' is file.'
                printf $2' is file.'\\n > $1/$2
        else
                echo $2' is not file.'
                touch $1/$2
                printf $2' file is created.'\\n > $1/$2
        fi

        ##### Example 2. Arithmetic Comparison Operator
        if [ $3 -gt 1 ]; then
                echo $3' is greater than 1.'
                printf $3' is greater than 1.'\\n >> $1/$2
        elif [ $3 -eq 1 ]; then
                echo $3' is equal to 1.'
                printf $3' is equal to 1.'\\n >> $1/$2
        else
                echo $3' is less than 1.'
                printf $3' is less than 1.'\\n >> $1/$2
        fi

        ##### Example 3. String Comparison Operator
        if [ $4 == "BMW" -o $5 == "Martiz" ]; then

                if [ $4 == "BMW" ]; then
                        echo $4' is very expensive car.'
                        printf $4' is very expensive car.'\\n >> $1/$2
                fi

                if [ $5 == "Martiz" ]; then
                        echo $5' is twins transformer.'
                        printf $5' is twins transformer.'\\n >> $1/$2
                fi

        else

                echo 'Both '$4' and '$5' are not mine.'
                printf 'Both '$4' and '$5' are not mine.'\\n >> $1/$2

        fi

fi


위와 같이 Shell Script를 작성하니 조금 복잡해 보이긴 하지만 50줄도 안되는 아주 간단한 예제입니다.

 

스크립트에 문단이라는 국어적 표현이 맞을지 모르나, 문단별로 나누어서 설명 드리도록 하겠습니다.

 

먼저 위 예제 스크립트는 외부로부터 변수를 받아 처리하기 위해 스크립트 내부적으로『 위치 매개변수($1, $2, $3, ..) 』를 사용하고 있습니다.

 

그리고 제일 첫 번째 라인은 해당 Shell Script 파일을 어떤 Shell로 처리할 것인지를 선언하는 부분입니다.


#!/bin/sh



다들 아시겠지만 Shell에는 bash, ksh, csh, tcsh 등 여러 종류가 있는데, 해당 OS에서 사용 가능한 Shell 이 어떤 것들이 있는지를 확인해 보고 싶다면 bin 디렉토리로 이동하여 다음과 같은 명령어를 수행시켜 보면 됩니다.


# ls *sh*


또한, 현재 접속한 터미널에서 사용하는 기본 Shell이 무엇인지 확인하려면, 다음의 명령어를 수행합니다.

# echo $SHELL


저의 예제는 ksh 또는 bash Shell 기준으로 만들어졌습니다.

 

이렇게 선언부를 간단히 처리하고 본격적인 Shell Script를 작성하시면 됩니다.

 


1) 첫 번째 문단


if [ -d $1 ]; then                                                   // 첫 번째 매개변수값이 디렉토리라면,

        cd $1                                                           // 해당 디렉토리로 이동

        ##### Example 1. Test Operator              // 주석
        if [ -f $2 ]; then                                           // 두 번째 매개변수값이 파일이라면,
                echo $2' is file.'                                   // '$2 is file.' 이라는 문장을 echo 한다.
                printf $2' is file.'\\n > $1/$2                // '$2 is file.' 이라는 문장을 $1 디렉토리 밑에 $2 파일에 printf 하고 줄바꿈(\n: 개행문자)한다.
        else                                                            // 두 번째 매개변수값이 파일이 아니라면,
                echo $2' is not file.'                            // '$2 is not file.' 이라는 문장을 echo 한다.
                touch $1/$2                                       // $1 디렉토리 밑에 $2 파일을 만든다.
                printf $2' file is created.'\\n > $1/$2  // '$2 file is created.' 라는 문장을 $2 파일에 printf 하고 줄바꿈(\\n) 한다.

        fi


라인별 설명은 위 내용을 참조하시면 되겠고,

 

결국 위 구문을 말로 풀어내자면,

 

첫 번째 매개변수값에 해당하는 디렉토리($1)가 존재하면 change directory하고 output으로 생성할 파일($2)이 있는지 확인한 후(없으면 만들고), 조건식의 true 여부에 따라 각각에 해당하는 문장을 echo 및 printf 하겠다는 것입니다.

 

별로 어렵지 않죠?

 

위 구문 중 touch 명령 라인은 굳이 사용하지 않아도 바로 밑 라인의 '>(redirection)' command 에 의해 자동 파일 생성하게 됩니다.

 

echo나 printf 구문 뒤에는 위와 같이 문자열 등이 올 수 있는데, 문자열은 반드시 '(single quotation) 나 "(double quotation)로 wrap 해 주셔야 하며, 위치 매개변수의 경우엔 quotation 바깥에 명시해 주어야만 실제 매개변수값을 전달받을 수 있습니다.(echo $2' is file.')



2) 두 번째 문단 


        ##### Example 2. Arithmetic Comparison Operator
        if [ $3 -gt 1 ]; then
                echo $3' is greater than 1.'
                printf $3' is greater than 1.'\\n >> $1/$2
        elif [ $3 -eq 1 ]; then
                echo $3' is equal to 1.'
                printf $3' is equal to 1.'\\n >> $1/$2
        else
                echo $3' is less than 1.'
                printf $3' is less than 1.'\\n >> $1/$2

        fi


두 번째 문단에서 주의 깊게 살펴 보셔야할 부분은 elif 구문 뒤에 조건식이 들어간다는 것입니다.(지난 글에서는 언급이 없었네요.;;)

 

elif 구문이 else if 구문과 같으므로 당연히 조건식이 들어가야만 하겠죠.(조건식이 없어도 되는 것은 else 뿐입니다.)

 


3) 세 번째 문단 


        ##### Example 3. String Comparison Operator
        if [ $4 == "BMW" -o $5 == "Martiz" ]; then

                if [ $4 == "BMW" ]; then
                        echo $4' is very expensive car.'
                        printf $4' is very expensive car.'\\n >> $1/$2
                fi

                if [ $5 == "Martiz" ]; then
                        echo $5' is twins transformer.'
                        printf $5' is twins transformer.'\\n >> $1/$2
                fi

        else

                echo 'Both '$4' and '$5' are not mine.'
                printf 'Both '$4' and '$5' are not mine.'\\n >> $1/$2

        fi


세 번째 문단은 문자열 비교 예시로써, 앞서 제가 올린 글들을 잘 읽어 보셨다면 역시 별 무리 없이 이해하실 수 있을 것입니다.

 

위 문단에서 한 가지 언급 드리고 싶은 것은 문자열 비교 시에 대소문자를 구분한다는 것입니다.

 

만일 네 번째 위치 매개변수의 값으로 'bmw' 라는 소문자 문자열이 입력되었다면, 위 문단의 두 번째 조건식($4 == "BMW")에서 false 를 리턴하겠죠.

 

이제 이렇게 작성된 스크립트를 실행시키려면, 사용자가 로그인한 바로 그 계정에서 해당 스크립트에 대한 실행 권한이 있어야 합니다.

 

즉, vi 편집기로 위와 같이 작성 완료한 후에 스크립트 실행 전, 다음과 같이 모드를 변경해 주어야 합니다.


# chmod 755 IfTest.sh

# ls -l IfTest.sh

-rwxr-xr-x       1 root        root           1185  Aug    9  16:52   IfTest.sh


권한이나 모드 변경에 대한 것은 이 글을 읽고 있는 분들께서 사전에 알고 계실 것이라 믿고 설명을 생략하도록 하겠습니다.

 

위와 같이 하였다면 이제 다음과 같이 인자를 주고 실행시킨 후, 결과가 잘 나오는지를 확인하면 됩니다.


./IfTest.sh /opt IfTestResult.txt 0 bmw Martiz



이상으로 if문을 포함하는 Shell Script에 대하여 예시를 통해 한 번 알아보았습니다.

posted by 박현명

(3) 논리 연산자

 

[ ](대괄호) 안의 조건식에 두 개 이상의 조건을 넣어야 할 경우 논리 연산자를 사용할 수 있으며, 연산자의 종류 및 기능은 다음과 같습니다.


-a : and, &&

-o : or, ||



논리 연산자의 사용법은 다음과 같습니다.


if [ 조건식1 -a 조건식2 ]; then

    ~

else

    ~

fi



다들 알고 계시겠지만, and 논리 연산자의 경우 '조건식1' 이 true 이어야지만 '조건식2' 로 넘어가며, '조건식1' 이 false인 경우 '조건식2' 의 체크없이 바로 else 구문으로 넘어가게 됩니다.

 

사용 예를 들자면, 다음과 같습니다.


if [ -f ${file1} -a -f ${file2} ]; then

    echo 'file1과 file2는 모두 파일입니다.'

else

    echo 'file1과 file2가 모두 파일인 것은 아닙니다.'

fi


이상은 논리 연산자에 대한 사용법에 대해서 설명 드렸고, 다음은 자주 사용되는 연산자는 아니지만 추가로 덧붙입니다.

 


(4) 파일 생성 시기 비교 연산자

 

[ ](대괄호) 안의 조건식에 두 개의 파일 중 어떤 것이 더 먼저, 혹은 나중에 생성되었는지 알고자 할 경우 다음과 같은 비교 연산자를 사용할 수 있습니다.


f1 -nt f2 : f1파일이 f2파일보다 최신임(newer than)

f1 -ot f2 : f1파일이 f2파일보다 예전것임(older than)



위 연산자에 대한 예시는 따로 들지 않겠습니다.

 

이상으로 if문에서 자주 사용되는 연산자들과 사용법에 대해서 알아보았구요.

 

예제 스크립트로 바로 넘어갈까 했는데 한 가지 더 설명드리고 예제 스크립트를 보여 드리는 편이 나을 것 같아서 잠깐 언급하도록 하겠습니다.

 


* Shell Script 에서 input 값 받아 처리하기

 

우리가 Shell Script를 작성하다 보면 외부로부터 받은 input 값을 스크립트 내부에서 처리해야 하는 경우가 종종 발생하게 됩니다.

 

가령, ./test.sh [input_parameter1] [input_parameter2] 와 같은 식으로 말이죠.

 

위와 같이 외부로부터 받은 input 값은『 위치 매개변수 』를 통하여 처리하면 됩니다.


$1, $2, $3, ... : input_parameter1은 $1 위치 매개변수로, input_parameter2는 $2 위치 매개변수로 처리

※ $0 : 해당 Shell Script의 이름



예를 들어, 스크립트로 넘어온 input 값이 0인지 아닌지 비교하는 스크립트(ex. number_compare.sh)를 작성하고 싶다 하면 다음과 같이 하면 됩니다.


#!/bin/sh

if [ $1 -eq 0 ]; then

    echo 'input 값은 0 입니다.'

else

    echo 'input 값은 0 이 아닙니다.'

fi




위와 같이 작성하고 다음과 같이 실행시키면 됩니다.


./number_compare.sh 숫자






posted by 박현명

(2) 테스트 연산자

[ ](대괄호) 안의 조건식에는 여러 종류의 테스트 연산자를 사용할 수 있으며, 연산자의 종류 및 기능은 다음과 같습니다.

* 다음 조건을 충족시킬 경우, true 리턴

-e : 존재하는 파일
-f : 보통 파일
-d : 파일이 디렉토리
-s : 파일 크기가 0이 아님
-z : 문자열이 null임. 길이가 0
-n : 문자열이 null이 아님
-c : 파일이 문자 디바이스(키보드, 모뎀, 사운드 카드..)
-b : 파일이 블럭 디바이스(플로피나 CD롬)
-p : 파일이 파이프
-h : 파일이 하드 링크
-L : 파일이 심볼릭 링크
-S : 파일이 소켓
-t : 파일 디스크립터가 터미널 디바이스와 연관 있음
-r : 테스트를 돌리는 사용자가 읽기 퍼미션을 갖고 있음
-w : 테스트를 돌리는 사용자가 쓰기 퍼미션을 갖고 있음
-x : 테스트를 돌리는 사용자가 실행 퍼미션을 갖고 있음
-g : 파일이나 디렉토리에 set-group-id 플래그가 세팅되어 있음


가령 예를 들자면,

if [ -d /tmp ]; then

    echo '/tmp 디렉토리가 존재합니다.'

else

    echo '/tmp 디렉토리가 존재하지 않습니다.'

fi


위와 같이 사용하면 됩니다.

파일과 관련한 연산자일 경우는 연산자 뒤에 파일명이, 디렉토리와 관련한 연산자일 경우는 연산자 뒤에 디렉토리명이 명시되어야 합니다.


다음은 산술 비교 연산자 및 문자열 비교 연산자입니다.

산술 비교 연산자

문자열 비교 연산자

-eq (equal)

== 

-ne (not equal)

!=

-gt (greater than)

 

-ge (greater than or equal)

 

-lt (less than)

 

-le (less than or equal)

 


산술 비교 연산자는 수치 비교를 위해 사용되며, 다음과 같이 사용됩니다.

if [ ${input} -eq 0 ]; then

    echo 'input 값은 0과 같습니다.'

else

    echo 'input 값은 0과 같지 않습니다.'

fi


문자열 비교 연산자는 문자열 비교를 위해 사용되고 대소문자를 구분하며, 다음과 같이 사용됩니다.

if [ ${input} == "Test" ]; then

    echo 'input 값은 Test 문자열과 같습니다.'

else

    echo 'input 값은 Test 문자열과 같지 않습니다.'

fi


'$(달러)' 문자로 시작되는 값은 변수를 의미합니다.


posted by 박현명

1. if문

(1) 기본 사용법 

if [ 조건식 ]; then          // if문 시작
    ~

elif

    ~

else

    ~

fi                                // if문 종료


if문은 IT업계에 종사하는 분이라면 굳이 개발자가 아니더라도 누구나 다 알고 계실 겁니다.

elif 는 else if 구문이라는 것도 다 아실 것이구요.


위 구문에서 한 가지 주의할 점은 if문 선언 시의 띄어쓰기와 세미콜론(;) 입니다.

if 와 [ ](대괄호) 사이는 반드시 한 칸 띄워주어야 합니다.(제가 Shell Script를 처음 작성할 때 이 띄어쓰기를 간과했다가 한참을 헤맸던 기억이..;;)

그리고 위와 같이 if 와 then 을 한 line에 나열하려면 반드시 세미콜론(;)을 사용해야 합니다.

세미콜론을 사용하지 않으려면 다음과 같이 if 다음 열에 then 을 사용해야 합니다.

if [ 조건식 ]

then                    // if문 시작

    ~

elif

    ~

else

    ~

fi                       // if문 종료


또한, 조건식을 넣는 부분에 [ ](대괄호) 대신 test 구문을 사용할 수도 있습니다.

if test 조건식

then                    // if문 시작

    ~

elif

    ~

else

    ~

fi                        // if문 종료


test 구문과 [ ](대괄호)는 동일한 기능을 하며, 취향에 따라 골라 쓰면 됩니다.


posted by 박현명
prev 1 next