"래퍼"란 시스템 명령어나 유틸리티들을 해당 매개변수들과 함께 쉘 스크립트로 만들어 두는 것을 말합니다. 명령어줄에서 아주 복잡하게 부를 명령어를 스크립트로 만들어 두면 실행 시킬 때 아주 간단해 집니다. 특히 sed와 awk에 이 쉘 래퍼를 쓰면 아주 좋습니다.
sed 나 awk 스크립트는 명령어 줄에서 sed -e 'commands'라고 치거나 awk 'commands'이라고 쳐서 실행 시킬 수 있습니다. 이런 스크립트를 Bash 스크립트 안에서 사용하게 되면 좀 더 간단하게 쓸 수 있고 "재사용"할 수 있습니다. 예를 들어 sed의 출력과 awk의 입력을 파이프로 연결하는 것처럼 sed와 awk의 기능을 연결해서도 쓸 수도 있습니다. 저장된 실행 파일이라면 다시 치는 불편함 없이 원래 형태나 약간 변경된 형태로 계속 실행 시킬수가 있습니다.
예 34-1. 쉘 래퍼(shell wrapper)
#!/bin/bash # 파일에서 빈 줄을 지워주는 간단한 스크립트. # 인자 확인 안 함. # 명령어줄에서 # sed -e '/^$/d' filename # 이라고 하는 것과 똑같음. sed -e /^$/d "$1" # '-e'는 다음에 나오는 것을 "편집" 명령어로 해석(여기서는 넣어도 되고 안 넣어도 됨). # '^'는 줄 처음, '$'는 줄 끝. # 줄 처음과 줄 끝 사이에 아무 것도 없는 것(빈 줄)과 일치. # 'd' 는 삭제 명령어. # 명령어줄 인자를 쿼우트 해 주면 파일이름에 #+ 공백문자나 특수문자가 들어가도 상관없습니다. exit 0 |
예 34-2. 조금 복잡한 쉘 래퍼(shell wapper)
#!/bin/bash # "subst", 파일에서 어떤 패턴을 다른 패턴으로 바꿔주는 스크립트. # 즉, "subst Smith Jones letter.txt". ARGS=3 E_BADARGS=65 # 필요한 인자가 빠져있음. if [ $# -ne "$ARGS" ] # 스크립트로 넘겨진 인자의 갯수를 확인(항상 이렇게 하세요). then echo "사용법: `basename $0` old-pattern new-pattern filename" exit $E_BADARGS fi old_pattern=$1 new_pattern=$2 if [ -f "$3" ] then file_name=$3 else echo "\"$3\" 은 없는 파일입니다." exit $E_BADARGS fi # 여기가 가장 중요한 부분입니다. sed -e "s/$old_pattern/$new_pattern/g" $file_name # 's'는 sed의 치환(substitution) 명령어이고, # /pattern/ 은 주소 매칭을 실행시킵니다. # 전역(global) 플래그인 "g"를 쓰면 단지 첫번째 일치하는 $old_pattern만 #+ 치환시키지 않고 각 줄에서 일치하는 "모든" $old_pattern을 치환시킵니다. # 더 자세한 설명은 'sed' 문서를 읽어보세요. exit 0 # 스크립트의 실행이 성공이라면 0을 리턴. |
예 34-3. awk 스크립트 쉘 래퍼(shell wrapper)
#!/bin/bash # 대상 파일에서 주어진 열을 다 더하기. ARGS=2 E_WRONGARGS=65 if [ $# -ne "$ARGS" ] # 명령어줄 인자 수가 적당한지 확인. then echo "사용법: `basename $0` filename column-number" exit $E_WRONGARGS fi filename=$1 column_number=$2 # 쉘 변수를 awk 에게 넘기는 것은 약간 까다롭습니다. # 더 자세한 것은 awk 문서를 참고하세요. # 여러줄짜리 awk 스크립트는 awk ' ..... ' 처럼 부르면 됩니다. # awk 스크립트 시작. # ----------------------------- awk ' { total += $'"${column_number}"' } END { print total } ' "$filename" # ----------------------------- # awk 스크립트 끝. # 쉘 스크립트에 내장된 awk 스크립트에게 쉘 변수를 넘기는 것은 # 안전하지 않을 수가 있기 때문에, Stephane Chazelas 가 다음과 같은 대안을 # 제안해 주었습니다: # --------------------------------------- # awk -v column_number="$column_number" ' # { total += $column_number # } # END { # print total # }' "$filename" # --------------------------------------- exit 0 |
하나로 된 만능 툴이나 스위스 군용 칼 같은 기능이 필요한 스크립트들을 위해 펄이 있습니다. 펄은 sed와 awk의 기능을 묶어 C 의 큰 서브셋으로 만듭니다. 모듈로 동작하며 객체 지향 프로그래밍에서 부엌 싱크대까지 모든 것을 지원합니다. 짧은 펄 스크립트는 쉘 스크립트 상에서 효과적으로 쓰일 수 있고, 펄이 쉘 스크립트를 완전히 대체할 수 있을 거란 얘기도 있지만 저자는 그렇게 생각하지 않습니다.
예 34-4. Bash 스크립트에 내장된 펄
#!/bin/bash # 펄 스크립트보다 쉘 스크립트가 먼저 올 수 있습니다. echo "\"$0\" 에서 내장된 펄 스크립트보다 먼저 등장." echo "===============================================================" perl -e 'print "내장된 펄 스크립트 부분.\n"' # sed 처럼 펄도 "-e" 옵션을 씁니다. echo "===============================================================" echo "하지만, 스크립트에는 쉘이나 시스템 명령어가 올 수도 있습니다." exit 0 |
심지어는 Bash 스크립트와 펄 스크립트를 한 파일에서 같이 쓸 수도 있습니다. 그 스크립트가 어떻게 불리냐에 따라 Bash 부분이 실행될지 펄 부분이 실행될지가 결정됩니다.
예 34-5. 하나로 묶인 Bash 스크립트와 펄 스크립트
#!/bin/bash # bashandperl.sh echo "스크립트의 Bash 쪽에서 보내는 축하 메세지." # 이 다음에 Bash 명령어가 더 올 수 있습니다. exit 0 # Bash 부분의 끝. # ======================================================= #!/usr/bin/perl # 이 부분은 -x 옵션을 줘야 실행됩니다. print "스크립트의 펄 쪽에서 보내는 축하 메세지.\n"; # 이 다음에 펄 명령어가 더 올 수 있습니다. # 펄 부분의 끝. |
bash$ bash bashandperl.sh 스크립트의 Bash 쪽에서 보내는 축하 메세지. bash$ perl -x bashandperl.sh 스크립트의 펄 쪽에서 보내는 축하 메세지. |