블로그 이미지
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  

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 박현명
2009.06.17 15:23 3. OS이야기

Shell Program 실행하기

    Shell Program 실행하는 방법

    1. 입력을 재지정(<)하는 방법
        $ sh < myfile
    입력 재지정(<)을 사용하므로 초보자는 사용하기가 어렵다.
    scripts에 매개변수를 제공할 수 없다.

    2. 매개변수로 scripts을 제공하는 방법
       $ sh myfile
    scripts에 매개변수를 제공할 수 있다. 즉,
       $ sh myfile parameters
    3. 실행 의무를 설정하는 방법
       $ ls -l myfile 
    	-rw-r--r       1  kc     other          68  1월 9일 11:15 myfile
       $ chmod a+x 
       $ ls -l myfile 
    	-rwxr-xr-x     1  kc    other          68  1월 9일 11:15 myfile
       $ myfile
    


Shell 변수

    명칭 변수 - 저장된 값이 실행되는 동안 변경될 수 있다.
    Shell 변수 - 텍스트 스트링을 저장.

    Shell 변수

    Shell 변수는 변수에게 할당된 값을 저장한다.
    [형식]
    $ variable_name=variable_value
    Shell 변수를 사용할 때의 주의할 점은 변수명과 변수값 사이의 '='에는 공백이 있어서는 안된다.
       $ name=gdhong   <-- name이라는 변수에 'gdhong'이라는 값을 배정.
       $ name = gdhong  <-- '='기호 전후에 공백이 있음.
             name: 없음         <-- error message 출력
       $
    

    기호 - Shell scripts 내부에서 일반 텍스트 스트링과 구분한다. 즉 $가 붙은 스트링을 변수 를 의미한다. 또한 $를 사용하여 변수의 값을 알아볼 수 있다.

    [형식]
    Shell scripts 내부에서 $varable_name

       $ name=gdhong   
       $ echo   $name
         gdhong
       $
    

    ', "기호 - 변수 내의 공백, 탭, 개행 등을 포함할 때 사용한다.(인용부호)

       $ name="Gildong Hong"
       $ echo  $name 
          Gildong Hong
       $ 
    

    Null String을 참조해도 아무 상관없음

       $ echo  $she is very beautiful.
          is very beautiful.
       $ she=Mary
       $ echo  $she is very beautiful.
          Mary is very beautiful.
       $ 
    
    변수에값에서 ?와 *의 사용
       $ memo=a*
       $ echo "$memo"
          a* 
       $ echo  $memo
          a.html a.sql 
    
    중괄호({,}) - Shell scripts 내부에서 변수명 다음에 스트링이 이어질 때 사용한다.
    [ 형식]
    ${variable_name}string or " $variable_name"string
       $ os=WINDOWS
       $ echo   ${os}95
         WINDOWS95
    
    $ echo " $os"95 WINDOWS95 $

    변수의 삭제

       $ unset memo 
    

    읽기 전용 Shell 변수

    readonly - 읽기 전용 변수로 설정한다. 즉 변수 내용을 다른 것으로 바꿀 수 없다.
    주의) 읽기 전용변수로 설정되면 다시는 쓰기 가능으로 바꾸는 방법은 없다.

    [형식]
       $ readonly variable_name    <-- 읽기 전용 설정
    
       $ readonly     <-- 지정된 읽기 전용 변수의 출력
    
       $ readonly name    <-- 읽기 전용의 설정
       $ name=gdhong    <-- 변수 값의 변경
          name: 읽기 전용임
       $ echo   $name
          Gildong Hong
       $ readonly         <-- 읽기 전용 변수의 출력
         읽기전용 name
       $
    

    Shell 변수 export

    사용자가 지정한 변수는 현재의 Shell에서만 사용 가능하다. export로 표시된 변수는 Shell이 생성한 어떤 명령에도 사용할 수 있다.

    [형식]
       $ export variable_name        <-- export로 표시
    
       $ export                              <-- export 변수의 출력
    
       $ cat  example                    <-- example file의 생성 
       echo    $he likes Mary.
       $ he=John
       $ example
        likes Mary.
       $ export he 
       $ example
        John likes Mary.
       $ 
    
    [예제]
       $ cat extest1     
            cheese=american
            echo "extest1:$cheese"
            subtest
            echo "extest1:$cheese"
    
       $ cat subtest                    
            echo "subtest1:$cheese"
            cheese=swiss
            echo "subtest2:$cheese"
    
       $ extest1                    
            extest1:american
            subtest1:
            subtest2:swiss
            subtest2:american
     
    
       $ extest1 첫 line에 아래 line추가    
            export cheese            -->cheese변수를 subtest에서 사용할 수 있도록 지정 
     
       $ extest1                    
            extest1:american
            subtest1:american 
            subtest2:swiss
            subtest2:american
    

    read

    사용자가 입력한 값을 받아 사용자가 생성한 변수에 저장

    [예제 1]
       $ cat read1      
          echo "Go ahead: \c"
          read firstline
          echo "You entered :$fistline"
     
       $ read1                   
          Go ahead : This is a line
          You entered : This is a line
    
    [예제 2]
    : $filename이 이중인용부호로 쌓여있을 때 *는 확장되지 않음
       $ cat read1_no_quote      
          Go ahead : * 
          You entered : a.sql a.html b.html 
    
    [예제 3]
    :명령을 실행하고 thanks를 표시
       $ cat read2 
          echo "Enter a command : \c"
          read command
          $command
          echo thanks
         
       $ read2 
          Enter a command : who
          gdhong    pts/6       12월 1일  00:00
          sun       pts/10      12월 2일  07:34
          thanks
    

    Shell 변수를 대화형으로 사용하기

    Shell 변수는 대화형 명령 중에서 긴 텍스트 스트링을 저장하는데 유용하게 사용될 수 있다. 자주 사용되는 긴 경로명이나 파일명을 Shell 변수로 지정해 두면 편리하게 사용할 수 있다.

    ex1) Shell 변수를 사용하지 않는 경우
       $ cd /home1/lab/dblab/gwjang/unix
       $ ls 
       $ ls /home1/lab/dblab/gwjang/unix
    
    ex2) Shell 변수를 사용하는 경우
       $ unix=/home1/lab/dblab/gwjang/unix
       $ cd    $unix
       $ ls
    
    $ ls $unix

    자동 Shell 변수

    다음은 변수들은 Shell에 의해서 자동으로 지정된다.
    $?마지막 실행된 명령이 돌려주는 최종값을 포함한다.
    $$Shell의 프로세스 ID를 포함한다.
    $!Shell이 실행시킨 마지막 백그라운드 프로세스의 번호를 포함한다.
    $-Shell이 기동될 때 Shell에 전달된 플래그 또는 set 명령을 사용해 지정된 플래그를 포함한다.
    $#Shell의 매개변수의 수를 포함한다.(Shell 프로그램의 매개변수-링크)
    $*현재 매개변수 리스트를 포함한다. $* = $1, $2, ... 등과 같고 " $*" = " $1, $2, ..."와 같다.
    $@현재 매개변수 리스트를 포함한다. 인용부호없이 $@를 쓰면 공백을 포함하고 있는 매개 변수를 별개의 매개변수로 분리한다. $@= $1, $2, ... 등과 같고 " $@"= " $1", " $2", ... 등과 같다.

    [예제 1]

       $ echo$$     
            2788 
       $ ps                    
            PID   TTY    TIME    COMD
           2740   pts/12  0:00   csh
           2778   pts/12  0:00   sh
    
    [예제 2]
       $ ps &     
          3395 
    $ PID   TTY    TIME    COMD  
        2740   pts/12  0:00   csh
        2778   pts/12  0:00   sh
    
       echo $!  
          3395   
    
    [예제 3]
       $ cat num_args     
            echo "This shell script was called with $# arguments"
          $ num_args a b c
            This shell script was called with 3 arguments
    
    [예제 4]
       $ date      
          2000년 1월 1일 토요일 오전 00시 00분 00초
     
       $ cat dateset   
          set `date`
          echo
          echo "Argument 1: $1"
          echo "Argument 2: $2"
          echo "Argument 3: $3"
          echo "Argument 4: $4"
          echo
          echo $2 $3, $6
    
       $ dateset  
          2000년 1월 1일 토요일 오전 00시 00분 00초
    
          Argument 1:토요일
          Argument 2:1월   
          Argument 3:1일
          Argument 4:00시 00분 00초
         
          1월 1일, 00시
    

    표준 Shell 변수

    사용자는 set 명령을 사용해 모든 현재 변수의 전체 리스트를 볼수 있다.(Shell 프로그램의 매개 변수-링크) 아래의 예는 cosmos의 set 명령의 보기이다.

       $ set 
    

    [중요한 표준 변수 리스트]
    $HOME사용자의 홈 디렉토리명을 포함한다. 로그인시 지정되며, UNIX 파일 시스템 내에 저장된 파일을 액세스할 필요가 있는 프로그램에 의해 사용된다.(.profile, .login, .cshrc, 등)
    $LOGNAME사용자의 로그인 명이다.($USER)
    $MAIL or $MAILPATH 메일 도착을 알고자 할 때 사용된다. 둘 중 하나만 지정되야 한다. $MAIL이 지정되면, 메일이 도착할 파일명이 지정되어야 한다. $MAILPATH가 지정되면, 콜론(:)으로 분리된 메일 파일의 리스트이어야 한다. 이들 변수는 메일 프로그램이 E-Mail을 어디에 놓아야 하는지를 지정하지는 않지만, 새로운 메일이 도착하면 Shell이 어디를 찾아야 하는지를 지정한다.
    $MAILCHECK메일 파일을 검사는 초 단위의 간격
    $SHELL로그인 Shell명이다. vi 텍스트 에디터와 같이 프로그램을 빠져나가지 않고도 또 다른 대화형 Shell을 부르기를 원하는 프로그램에서 사용된다.
    $PS1 Shell이 사용할 첫 번째 프롬프트 스트링이다. 디폴트는 $이다.
    $PS2 두 번째 프롬프트 스트링이다. 명령이 완전히 끝나지 않고 Shell이 또 다른 입력 행을 요구할 때 사용된다. 디폴트는 >이다.
    $TERM 사용자의 터미널 형을 포함한다. vi 같은 어떤 명령은 정확한 결과를 내기 위해 사용중인 터미널의 종류가 무엇인지를 알 필요가 있다.

    검색 경로

    Shell이 사용자의 명령을 어디에서찾아야 하는가에 관한 디렉토리 리스트이다. 대부분의 검색 경 로는 사용자의 홈 디렉토리, /bin, /usr/bin을 포함한다. 이것은 대부분의 실행 명령어들을 bin이라 는 디렉토리 밑에 저장하고 있기 때문이다. 그리고 실행 프로그램들은 이진 파일로 저장되어 있 다. 이러한 검색 경로는 검색할 추가 디렉토리를 설정한다. 만약에 검색 경로 내의 디렉토리에서 명령(파일)이 발견되지 않으면 Shell은 포로그램이 없다는 에러 메시지를 출력한다. 현재 Shell의 검색 경로의 설정은 .profile(Bourne Shell), .cshrc(C Shell)에서 지정할 수 있으며, echo 명령으로 현재 검색 경로를 출력할 수 있다.
    ex) 검색 경로의 출력
       $ echo   $PATH 
        :/usr/bin:/usr
       $ 
    
    검색 경로에서 콜론(:)은 널(null) 디렉토리를 나타낸다. 이것은 현재의 디렉토리를 의미한다.

    비지정 변수

    Shell에서는 지정되지 않은 변수도 사용할 수 있다. 비지정 변수를 사용할 수 있는 방법은 다음과 같다.
    ${varable:-word}variable이 지정되고 널이 아니면 그 값을 사용한다. 그렇지 않으면 word의 값이 사용되고 variable은 변하지 않는다.
    ${varable:=word}variable이 지정되고 널이 아니면 그 값을 사용한다. 그렇지 않으면 word의 값이 variable에 배정되고, 이 새로운 값이 사용된다.
    ${varable:?word} variable이 지정되고 널이 아니면 그 값을 사용한다. 그렇지 않으면 에러 메세지인 word를 출력하고, Shell scripts를 종료한다. word가 생략되면, shell scripts를 종료하기 전에 "parameter null or not set"이라는메세지를 출력한다.
    ${var:+word} variablerk 지정되고 널이 아니면 word로 대치한다. 그렇지 않으면 아무것도 대치하지 않는다.


    $ echo $she likes Jon. likes Jon. $ echo ${she:-Mary} likes John. Mary likes John. $ echo $she likes John. likes John. $ echo ${she:?Error} likes John. she: Error $ echo ${she:+Jane} likes John. likes John. $ echo ${she:=Sue} likes John. Sue likes John. $ echo $she likes John. Sue likes John. $ echo ${she:?Error} likes John. Sue likes John. $

    set명령의 -u 옵션을 지정하면 비지정 변수의 사용을 막을 수 있다.
    ex) 비지정 변수의 사용
       $ echo    $fruit apple
          apple
       $ set -u
       $ echo   $fruit apple
           fruit: 파라미터가 설정되지 않음
       $
    


특수 문자의 인용

    UNIX Shell에서 특수 문자를 인용하는 방법이다.
    백슬래쉬(\)
    백슬래쉬 뒤에 오는 문자를 인용
       $ echo   $HOME
         /home1/lab/dblab/gwjang
       $ echo \$HOME
       $HOME
       $
    

    단일 인용부호(',')
    단일 인용부호로 묶은 문자를 인용. 어떤 해석도 발생하자 않는다.

       $ echo '$HOME'
       $HOME
       $
    

    이중 인용부호(",")
    이중 인용부호로 묶은 문자는 \, ", ", $를 제외하고 인용. 명령과 파라미터 변수 대치가 이중 인 용부호 안에서 발생한다.

       $ echo " $HOME"
         /home1/lab/dblab/gwjang
       $
    
    그렇다면 다음 세 개의 명령의 차이는 무엇일까?
       $ name='Gildong Hong'
       $ name="Gildong Hong"
       $ name=Gildong\ Hong
       $ echo   $name
          Gildong Hong
       $
    

명령 종결 상태

    UNIX 시스템은 프로그램이 성공적으로 실행되면, 0(zero)을 리턴(return)한다. 에러의 경우는 1 또는 2를 리턴한다.
    Name          I/O             File Descriptor
    stdin              input           0
    stdout          output           1
    stderr           error output    2
    user-defined    input/output     3-19
    

    $ pwd /home1/lab/dblab/gwjang $ echo $? 0 <-- 성공적으로 수행 $ ls /test /test: 해당 파일이나 디렉토리가 없음 $ echo $? 2 <-- 에러 $ echo $? 0 $ $?는 마지막 멸령의 종결 상태만을 반영한다.

단순 조건문

    && 연산자
    첫 번째 명령이 성공적(리턴 0)으로 수행될 때에만 실행
       $ ls -l >/dev/null && echo Sucess!
          Sucess!
       $ 
    
    || 연산자
    첫 번째 명령이 실행 실패(0이외의 종결 상태)일 때에만 실행
       $ ls -l test || echo Failed...
        test: 해당 파일이나 디렉토리가 없음
        Failed...
    
    ture : 0의 종결 상태를 리턴
    false : 0 이외의 종결 상태를 리턴
    true와 false는 if, while과 같은 조건문에서 자주 사용된다.
       $ true && echo TRUE
        TRUE
       $ false || echo FALSE
         FALSE
       $
    

단순 명령, 파이프라인, 리스트

    다음은 리스트의 요소를 분리하는 분리자들이다.
    ;       순차실행
    |       파이프 라인 실행
    &      백그라운드 실행
    &&     조건실행(true)
    ||       조건실행(false)
    

    IF 조건문



    [형식 1]
    if [ conditons ] 
    then 
      command_list
    else
      command_list
    fi
    

    [형식 2]
    if [ conditons ] 
    then 
      command_list
    fi
    

    [형식 3]
    if [ conditons ] 
    then 
      command_list
    elif [ conditons ]
    then 
      command_list
    else
      command_list
    fi
    

    ex) 다음은 파일이 존재하면 내용을 보여주고, 그렇지 않으면 파일을 생성한다.
    if [ -r filename ]
    then
      cat filename
    else 
      echo "Enter the data for filename"
      cat > filename
    fi
    


Shell 프로그램 매개변수

    $1은 명령행의 첫 번째 매개변수, $2은 명령행의 두 번째 매개변수, ...를 나타낸다.
    $0는 현재 실행중인 Shell 프로그램을 나타낸다. 다음은 Shell 매개변수를 나타내는 표이다.
    Bourne ShellC Shell설명
    $#$#매개변수의 수
    $0$0명령어 이름
    $1, $2, ...$1, $2, ...매개변수

    $argv[n]매개변수 $1, ...
    $*$*, $argv[*]$1, $2, ...
    $@
    $1, $2, ...
    $-
    set 명령의 Shell options
    $?
    마지막 명령의 리턴 값
    $$$$현재 명령의 프로세스 번호
    $!
    마지막 백그라운드 명령의 프로세스 번호

    ex) 다음은 네 개의 매개 변수를 입력 받아서 출력하는 예이다.
    if [  $# -eq 4 ]
    then
      echo "command is  $0 and arguments are  $1, $2,  $3, $4."
    else
      echo Syntax Error:  $0 arg1 arg2 arg3 arg4
    fi
    

While과 Until 조건 루프


For 문의 형식

    for variable_name in value1 value2 . . .
    do
      action on   $variable_name
    done
    

Case 문


    <형식>
    case $variable_name in 
    value1)
      action1  ;;
    value2)
      action2  ;;
    value3|value4)
      acton3  ;;
      . . .
    *)
      default action  ;;
    esac
    
    "*)"은 default action을 의미한다. match되는 것이 없으면 default action을 수행한다. 그리고 "|" 은 or를 타나낸다.
    ?는 한 문자와 대치될 수 있으며, 대괄호는 문자의 클래스를 정의한다.


Break와 Continue

    break는 while, for, until 등의 loop문에서 loop를 벗어날 수 있도록 해 준다. continue는 loop를 계속 수행할 수 있도록 해준다. 즉 loop내의 다음 반복을 수행한다.

명령 대치

    명령 대치는 명령어의 실행 결과를 변수의 값으로 지정되는 경우이다. 이것은 명령어가 역인용기 호(` : backquote)로 둘러 싸인다. 명령 대치는 Shell 변수에 대한 산술 연산을 수행하는데 자주 사용한다.
       $ today=`date`
       $ echo  $today
         1997년 1월 28일 수요일 오후 07시 13분 27초
       $
    

Shell 대치


    명령어 대치 : `command`
    변수 대치 : $variable_name

Here Documents

    Here documents는 Shell 프로그램 내에서 표준 입력을 일시적으로 재지정하는 데 사용한다.

    [형식]

    command args <<symbol
      . . . documents . . .
    symbol
    

    << 이후의 symbol은 here document의 끝을 나타낸다.

Shell 함수

    Bourne Shell의 약점 중의 하나는 함수가 부족하다는 것이다.
    Shell 함수의 구문은 다음과 같다.
    function_name()
    {
      statements
    }
    
    Shell 함수는 Shell scripts의 맨 위에 정의되어야 한다.

Set - 변수출력과 Shell 운영 모드 지정

    set은 Shell 내부 옵션의 지정을 제어하고, 값을 Shell의 위치 파라미터로 옮기는 역할을 한다.
    set의 옵션
    -e명령이 실패하면 즉시 탈출한다.
    -f파일명 생성을 못하게 한다.
    -n명령을 실행하지 않고 읽는다. 이것은 실제 실행시키지는 않고 Shell 대본의 구문을 테스트하고자 할 때 유용하다. Shell scripts 디버깅 때 자주 사용
    -i대화형 쉘을 실행한다. terminate 신호는 무시된다. interrupt 신호는 받아들였다가 무시되는데, 인터럽트가 되도록 기다리게 한다.
    -t한 명령을 실행한 후 탈출한다.
    -u비지정 변수에 대한 참조를 에러로 한다.
    -vvervose 모드를 설정한다. Shell scripts 디버깅 때 자주 사용
    -x실행될 때 +가 앞에 있는 각 명령을 출력한다. Shell scripts 디버깅 때 자주 사용
    - -v와 -x 디버깅 플래그를 해제한다.
    --플래그 옵션 중의 어느 것도 변경되지 않는다.

Test([, ]) - 조건 평가

    test 명령어는 주어진 이름이 파일이나 디렉토리이면, 그것을 읽을 수 있는지(readable), 쓸 수 있 는지(writable), 실행할 수 있는지(executable) 여부를 결정할 수 있다. 그리고 두 스트링 혹은 수 치(integer)가 보다 큰지(greater than), 보다 작은지(less than), 같은지(equal)를 결정할 수 있다. 또한 test의 특징은 AND, OR, NOT logic을 허락한다.
    test의 옵션
    파일 액세스 테스트
    -b filefile이 블록 특수 파일이면 리턴 True(0)
    -c filefile이 문자 특수 파일이면 리턴 True(0)
    -d filefile이 디렉토리 파일이면 리턴 True(0)
    -f filefile이 보통 특수 파일이면 리턴 True(0)
    -g filefile이 set-group-ID 권한을 가지면 리턴 True(0)
    -h filefile이 기호 링크이면 리턴 True(0)
    -k file file이 스티키(sticky) 비트 지정을 가지면 리턴 True(0)
    -L file file이 기호 링크이면 리턴 True(0)
    -p file file이 이름있는 파이프이면 리턴 True(0)
    -r file file이 읽기 가능이면 리턴 True(0)
    -s file file이 1byte 이상의 길이이면 리턴 True(0)
    -t [n] 파일 기술자 n(n이 제공되지 않으면 1로 간주)이 터미널을 참조하면 리턴 True(0)
    -u file file이 set-user-ID 권한을 가지면 리턴 True(0)
    -w file file이 쓰기 가능이면 리턴 True(0)
    -x file file이 실행 가능이면 리턴 True(0)
    스트링 비교
    -n s1 스트링 s1이 길이가 0 이상이면 리턴 True(0)
    s1 스트링 s1이 널이 아니면 리턴 True(0)
    -z s1 스트링 s1의 길이가 0 이면 리턴 True(0)
    s1 = s2 두 개의 스트링이 같으면 리턴 True(0)
    s1 != s2두 개의 스트링이 같지 않으면 리턴 True(0)
    수치 비교
    -eg 같음 -gt 보다 큼 -ge 크거나 같음
    -ng 같지 않음 -lt 보다 작음 -le 작거나 같음
    논리 연산
    ! NOT -a AND -o OR

Expr - 표현식 평가

    expr 명령은 범용의 정수 산술 프로그램이다. expr은 그 결과가 0이 아니면 참이고, 그 이외에는 거짓을 리턴한다.

    expr 연산자

    expr \| expr 왼쪽 표현식이 널이 아니고 0이 아니면 왼쪽 표현식을 돌려주고, 그렇 지 않으면 오른쪽 표현식을 돌려준다.
    expr \& expr 양쪽 모두의 표현식이 널이 아니고 0이 아니면 왼쪽 표현식을 돌려주 고, 그렇지 않으면 0을 돌려준다.
    expr cmp-op expr비교가 참이면 1을 돌려주고, 그렇지 않으면 0을 돌려주다.
    양쪽 표현식이 모두 수치 비교이고, 그렇지 않으면 텍스트 비교이다.

    \>     =     \>=      \<     !=      \<=
    expr add-op expr두 개의 표현식을 더하거나 뺀다.
    +    -
    expr mul-op expr곱하고 나누거나 나머지를 계산한다.
    \*      /      %
    expr : regexp 고정 스트링인 expr과 다음 만능문자를 포함할 수 있는 정규식인 regexp를 비교한다.
    .      어떤 한 문자와도 부합한다.
    $      검색을 스트링의 끝에 한정한다.
    [list]      리스트 내의 어떤 한 문자와도 부합한다.
    *      선행하는 한 문자 정규식의 0 이상의 것과 부합한다.
    \(\)     부합의 괄호 부분을 돌려준다. 이 옵션이 없으면, 결과는 부합 하는 길이이거나 부합되는 것이 없다는 의미의 0 중의 하나이다.

    $ tty
        /dev/pts9
    $  expr `tty` : ".*\(.\)\$"
        9
    $
    


Ulimit - 자원 제한의 지정과 출력

    ulimit 명령은 여러 자원의 제한을 지정한다.
    Ulimit의 옵션
    -a제한 리스트 보기
    -H강한 제한 지정
    -S약한 제한 지정(default)
    -c512byte 블록 단위의 최대 코어 덤프 파일 크기
    -dKbyte 단위의 최대 데이타 세그먼트 크기
    -fKbyte 단위의 최대 파일 생성 크기
    -n파일 지시자의 최대 수
    -sKbyte 단위의 최대 스택 세그먼트 크기
    -t초 단위의 최대 CPU 시간
    -vKbyte 단위의 최대 가상 기억장치 크기

    $ ulimit -a
         시간(초) 무제한
         파일(블럭) 무제한
         데이타(킬로바이트) 2097148
         스택(킬로바이트) 8192
         코어덤프(블럭) 무제한
         nofiles(설명자) 64
         메모리(킬로바이트) 무제한
    $
    


getopts - scripts에서의 옵션 관리

    getopts 명령은 옵션 플래그에 대해 System V 표준을 따르는 Shell 대본을 만든다. getopts 명령 은 두 개의 매개변수를 요구한다. 옵션 플래그의 리스트와 현재의 옵션 플래그가 저장될 변수이 다.


Bourne Shell의 내장 명령

    Shell 내장 명령

    :아무 일도 하지 않는다.
    .filefile에서 현재 Shell로 명령을 읽어들인다. ..profile을 입력하면 .profile이 실행된다.
    break[n]루프를 벗어난다. n이 지정되면 n레벨에서 벗어난다.
    continue [n]루프를 계속한다. n이 지정되면 n번째 외부 루프를 계속한다.
    cd [dir]홈 디렉토리로 이동하거나, 지정된 dir로 이동한다.
    echo [arg...]매개변수를 출력한다.
    eval cmd...cmd 내의 매개변수를 재평가한다. 이것은 Shell에게 강제로 다른 대치를 취해 매개변수 리스트로 전달한다.
    exec cmd...현재 실행중인 Shell의 위치에서 cmd를 실행한다. 이것은 현재 Shell을 새로운 프로세스로 대치하도록 하는 것으로, 사용자가 다른 Shell 또는 사용자 인터페이스로 전환할 수 있도록 한다.
    exit [n]n이 지정되면 n 종결 상태로 벗어난다.
    export [var...]매개변수가 없으면 새로운 환경 변수를 출력하고, 매개변수가 있으면 그들 변수는 export되는 것임을 나타낸다.
    newgrp [arg]exec newgrp arg와 동일하나, newgrp를 실행시켜 사용자를 새로운 Shell의 실행으로 생긴 새로운 그룹에 등록한다.
    pwd현재 디렉토리명을 출력한다.
    read var ...표준 입력에서 한 행을 읽는다.
    readonly [var...]읽기 전용 변수의 설정 및 리스트를 출력한다.
    return [n]종결 상태를 n으로 돌려주면서 함수에서 벗어난다.
    set [-op][arg...]Shell 옵션을 지정한다.
    shift [n]매개변수를 한 위치 또는 n위치 아래로 이동시킨다.
    test args ...표현식을 테스트한다.
    time 실행 시간을 출력한다.
    trap [cmd][n]...신호 n이 도착하면 cmd를 실행한다. cmd 텍스트는 두 번 조사된다. 가장 좋은 신호 처리기는 Shell 함수이다. cmd가 없으면, 신호 n은 디폴트로 재지정된다. cmd가 널이면 신호 n은 무시된다. n이 0이면 scripts에서 벗어난 곳에서 cmd가 실행된다.
    type [name ...]name이 어떻게 명령으로서 사용되는가를 출력한다. type ls는 ls is /usr/ls를 출력한다.
    ulimit args자원 제한을 지정한다.
    umask [nnn]생성 비트 마스크를 지정하고 출력한다. umask 022는 생성되는 파일과 디렉토리에 대하여 그룹과 다른 사람에게 쓰기를 허용하지 않는다.
    unset [name ...]지정된 변수 또는 함수의 지정을 해제한다.
    wait [n]PID가 n인 백그라운드 프로세스가 끝날 때까지 기다리거나 모든 백그라운드 프로세스가 끝날 때까지 기다린다.

    출처 : http://unix.co.kr/bbs/board.php?bo_table=02_11&wr_id=3

'3. OS이야기' 카테고리의 다른 글

HP core 파일 분석  (0) 2009.10.07
lsof 툴 다운로드  (0) 2009.09.29
Shell Programming  (0) 2009.06.17
rar처럼 tar로 분할 압축 하는 방법  (0) 2009.06.03
tar로 묶으면서 gzip으로 압축하는법  (0) 2009.06.03
AIX 업로드 속도관련 Network Kernel  (0) 2009.06.03
posted by DB,MW,OS OSSW(Open Source System SoftWare
TAG Shell
prev 1 next