이 문서에서는 리눅스의 쉘 스크립트로 코드를 짜는 방법을 알아본다.
쉘의 종류가 몇 개 있지만, 여기서는 bash shell에 대해 다룬다.
1. 쉘 종류 확인법 및 쉘 종류 바꾸는 법:
<Code:Shell Script> echo $SHELL </Code>
현재 사용 중인 쉘의 종류를 확인할 수 있다.
<Code:Shell Script> cat /etc/shells </Code> 현재 사용가능한 쉘의 종류를 확인할 수 있다.
만약 bash shell을 사용하고 있지 않고 사용가능한 쉘 목록에 bash shell 이 있다면
<Code:Shell Script> chsh Password: Changing the login shell for 'user name' Enter the new value, or press ENTER for the default Login Shell [/bin/sh]: /bin/bash </Code>
'user name'은 현재 로그인 되어 있는 유저의 계정명이고, 콜론 앞에 붙은 것은 시스템상에서 출력된 문구이다.
이렇게 shell을 바꾼 후에는 로그아웃 후에 다시 로그인을 해주어야 한다.
2. 좀 더 편한 사용자 환경을 위한 설정
<Code:Shell Script>
vi .bashrc
</Code>
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
<color #ed1c24> PATH=\$PATH:/bin:/usr/bin:$HOME:. </color>
<color #ed1c24> export PATH </color>
# If not running interactively, don't do anything
⁞
# for examples 와 # If not ~~ 사이에 빨간 문구를 넣어주면 자신 계정의 홈 폴더에 스크립트 파일을 생성한 후 경로지정 없이 바로 실행할 수 있다. PATH지정을 해주지 않으면 실행할 때마다 “~/script file” 이렇게 경로를 지정해서 실행을 해야한다.
시작
c든 파이썬이든 자바든 공통적으로 처음 프로그래밍을 시작하면
반드시 해보는 Hello World! 출력을 쉘 스크립트에서 해보겠다.
<Code:Shell Script> vi Hello.sh
#!/bin/bash echo “Hello World!” </Code>
vi로 Hello.sh 라는 파일을 하나 생성한 뒤 입력모드에서 “#!/bin/bash” 를 첫 줄에 써준다.
매직넘버라고 하여 bash shell에서 이 스크립트를 실행하겠다는 것을 시스템에 알려주는 역할을 한다.
echo는 c에서의 printf, 파이썬에서의 print 같은 역할을 한다. 코드 작성을 완료했으면 vi 모드에서 빠져나와
<Code:Shell Script> chmod +x Hello.sh </Code> 를 입력한다. 이유는 vi로 만든 파일을 시스템에서는 실행파일로 인식하지 않기 때문. 실행파일로 인식하게끔하는 명령어이다. 앞으로 #!/bin/bash와 chmod +x script_file 형태는 줄기차게 보게 될 것이다.
이제 script.sh 를 터미널 상에 입력하고 enter를 누르면 Hello World!가 출력될 것이다.
참고로 .sh를 붙인 것은 사용자끼리 “이것은 script file 이구나” 하는 것을 알기 쉽게 하기 위해 붙인 것이지, 윈도우 상의 .exe 같은 확장자 파일이 아니다. 즉, vi Hello 로 파일을 생성해서 코드를 작성한 뒤, 실행파일로 만들어 실행해도 결과는 똑같이 나온다.
디렉토리
<Code:Shell Script> vi dir.sh
#!/bin/bash
echo “$LOGNAME 님 안녕하세요.” echo “현재 directory는 `pwd`입니다.” echo “접속해 있는 시스템명은 `uname -n`입니다.” echo “현재 디렉터리의 파일목록은 아래와 같습니다.” ls echo “현재시간 : `date`” </Code>
$LOGNAME은 계정명을 나타내주는 변수다.
echo 내에서 시스템 명령어를 사용하고 싶으면 역따옴표(``)를 써야 한다. 따옴표('')가 아니다. 물결표를 입력할 때 쓰는 그 키이다. shift를 누르지 않고 물결표를 누르면 된다. esc 키 밑에 있는 키다.
배열
<Code:Shell Script> vi arr.sh
#!/bin/bash
echo -e “행복하세요? : \c” read answer echo “$answer 라고 답하셨네요.” echo -e “이름은 어떻게 되세요? : \c” read name echo “안녕하세요? $name 님” echo -n “좋아하는 음식 세가지를 적어주세요 : ” read -a dish echo “${dish[2]}을(를) 세번째로 입력하셨네요.” </Code>
echo -e “ ” 는 “ ” 안의 \c, \n 등과 같은 백슬래쉬로 표현되는 특수문자의 해석을 가능하게 해준다.
\c는 echo 명령의 줄바꿈 문자를 제거한다.
read name은 name이란 변수의 선언과 동시에 사용자로부터 입력을 받는다.
c의 scanf, 파이썬의 input과 비슷하다고 보면 될 것이다.
입력받은 변수값을 출력하려면 echo “\$name” 이렇게 달러표시를 변수 앞에 붙여서 출력하면 된다.
echo -n은 \c와 같은 역할을 하는데, “ ” 안에서 줄바꿈을 제거하느냐, 밖에서 제거하느냐의 차이가 있다.
read -a dish 는 dish라는 배열을 선언함과 동시에 배열 값을 사용자로부터 입력받는다. 배열의 인덱스는 0부터 시작한다.
입력받은 배열 값의 특정 인덱스를 출력하고 싶다면 echo “\${dish[인덱스 번호]}” 의 형식으로 출력한다. 받은 모든 배열 값을 출력하고 싶다면 echo “\${dish[@]}” 라고 하면 된다.
사칙연산
cal.sh <Code:Shell Script> #!/bin/bash
echo -e “숫자 두 개를 입력해주세요\c” read -a num
echo “${num[0]}와(과) ${num[1]}을(를) 입력하셨네요”
add=`echo “scale=2; ${num[0]} + ${num[1]}” |bc sub=`echo “scale=2; ${num[0]} - ${num[1]}” |bc mul=`echo “scale=2; ${num[0]} * ${num[1]}” |bc div=`echo “scale=2; ${num[0]} / ${num[1]}” |bc
echo “${num[0]} + ${num[1]} = $add” echo “${num[0]} - ${num[1]} = $sub” echo “${num[0]} * ${num[1]} = $mul” echo “${num[0]} / ${num[1]} = $div” </Code>
add=~~ 는 add 변수를 선언함과 동시에 초기값을 넣어주겠다는 의미다. <color #ed1c24>주의할 점은 변수명= 의 형태로 (변수명과 = 을 붙여서)써야 변수로 인식된다는 것이다.</color>
add= 뒤에 `echo ~~` 에서 왜 echo가 들어가야 하는지는 추후에 추가하도록 하겠다.
scale은 소수점 뒤의 몇 자리까지 표현할 지를 지정하는 인수이다. <color #ed1c24>scale을 지정하지 않으면 연산이 수행되지 않으니 반드시 지정해주어야 한다.</color>
scale=2; 에서 ;은 여기까지가 한 덩어리의 명령구문이라고 프로그램에 알려주는 기호다. ; 앞에 있는 명령구문까지 다 실행한 후, 다음 명령구문으로 넘어가는 것이다.
젤 뒤에 오는 |bc가 수식을 연산가능하게 만들어주는 핵심이다. |bc를 넣어주는 것으로 앞에 오는 + - * / 의 사칙연산이 수행된다.
스크립트로 awk 이용하기
우선 행렬 파일을 하나 만든다.
data <Code:Shell Script> 1 2 3 3 2 1 2 3 1 </Code>
위의 행렬은 예시이고 연산을 원하는 행렬 데이터를 넣으면 된다.
awk.sh <Code:Shell Script> #!/bin/bash
file=data column=3 cat $file | awk ‘{total+=$’$column’} END {print total}’ </Code>
위에서 행렬 데이터 파일을 data라고 했기 때문에 data라는 이름으로 변수 file을 초기화 시켰다.
awk로는 열 연산을 하는 것이 간편하기에 column이란 변수명을 사용했다.
이 예제에서는 3번째 열로 awk 연산을 할 것이기에 column에 3을 지정해주었다.
$file | awk : data파일로 awk를 실행하고
'{total+=$'$column'} : 변수 total을 선언한 후, 3열에 있는 숫자를 다 더해서 total에 다 집어넣는다.
END {print total} : 더하기 연산이 끝나고 나면 total의 값을 화면상에 출력한다.
awk가 pc에 없으면 이 예제는 실행이 되지 않을 수도 있다.
위치인자 표
위치 파라미터는 프로그램 실행 전에 사용자가 프로그램에게 '이런 값을 쓸 것이다' 하고 알려주면 프로그램이 실행된 후에 그 값을 받아주는 파라미터이다.
\$1 \$2 \$3 처럼 \$ + 숫자의 형태로 사용하며 1부터 10까지 10개를 이용할 수 있다.
10번째 위치 파라미터를 사용하려면 \${10} 처럼 중괄호로 10을 감싸주어야 한다.
이 외에도 특수한 위치 파라미터들도 있다. 위치 파라미터의 종류는 아래와 같다.
| 위치인자 | 의미 |
|---|---|
| $0 | 스크립트 파일의 이름 |
| $# | 위치 파라미터의 개수 |
| $* | 위치 파라미터의 모든 목록 |
| $@ | 위치 파라미터의 모든 목록 |
| “\$*” | 단일 아규먼트로 확장 ex) “\$1 \$2 \$3 …“ |
| “\$@“ | 아규먼트를 분리하여 확장 ex) “\$1” “\$2” “\$3” … |
| \$1 \$2 … \${10} | 개별 위치 파라미터, 사용자가 입력하는 파라미터. 10은 중괄호({})로 감싸주어야 한다 |
| $? | 종료 상태 변수. 프로그램 혹은 함수가 종료될 때 할당되는 값. 0이면 성공, 그 외는 실패 |
위치인자를 이용한 스크립트
parm.sh <Code:Shell Script> #!/bin/bash
echo $0 을 호출하였음 echo 첫 번째 : $1, 두 번째 : $2, 세 번째 : $3 echo 위치 파라미터 개수 : $# </Code>
parm.sh
parm.sh 홍길동
parm.sh 홍길동 임꺽정
parm.sh 홍길동 임꺽정 장길산
이 세 가지 경우 결과가 다르게 출력되는 것을 알 수 있을 것이다.
check.sh <Code:Shell Script> #!/bin/bash name=${1:?”이름 아규먼트가 필요합니다.”} echo 안녕하세요 $name 님. </Code>
${1:?”이름 아규먼트가 필요합니다.”} 는 $1에 인자가 들어오지 않았을 때 “이름 아규먼트가 필요합니다.” 라는 메시지를 출력하라는 의미이다.