LINUX/리눅스 쉘 스크립트 바이블 정리

[리눅스 바이블] 14. 사용자 입력 처리

은재정 2022. 3. 21. 20:31

 

매개변수 전달하기

쉘 스크립트에 데이터를 전달하는 가장 기본적인 방법은 커맨드라인 매개변수를 사용하는 것이다.

쉘 스크립트내에서 $1, $2와 같이 아홉번째 매개변수인 $9까지 사용할 수 있다.

아홉번째 매개변수 이후에는 ${10}과 같이 변수의 번호 주위에 중괄호를 사용해야 한다.

각 매개변수는 빈 칸으로 구분되므로 매개변수 값에 빈 칸을 포함하려면 따옴표를 사용해야 한다.

 

스크립트의 이름은 $0에 저장되어 있다.

다만 스크립트를 어디에서 실행하느냐에 따라 다른데, $0 변수는 스크립트의 전체 경로 및 이름으로 설정된다.

#!/bin/bash

echo "The zero parameter is set to $0"

 

위의 파일을 bash /home/user/test.sh와 같이 실행하게 되면 /home/user/test.sh로 출력된다.

경로 없이 스크립트의 이름만 사용하고 싶다면 basename 명령을 사용한다.

 

매개변수를 사용할 때에는 항상 매개변수가 세팅되어있는지 -n, -z를 이용해 확인해야 한다.

 

특수한 매개변수 사용하기

매개변수의 숫자는 $#에 저장되어 있다.

$$# 변수는 마지막 커맨드라인 매개변수에 상응한다고 생각할 수 있지만, 실제로는 ${!#}로 사용해야 한다.

#!/bin/bash
params=$#
echo "The last param is $params"
echo "The last param is ${!#}"

 

모든 데이터를 한꺼번에 얻기 위해서는 $*, $@ 변수를 사용한다.

$* 변수는 커맨드라인에 제공되는 모든 매개변수를 하나의 단어로 가지고,

$@ 변수는 커맨드라인에 제공되는 모든 매개변수를 분리된 단어로 가지고 있기 때문에 for문에서 유용하다.

 

shift 기능 사용하기

shift 명령을 사용하면 기본적으로 각 매개변수를 하나씩 왼쪽으로 옮긴다.

변수 $3은 $2로, $2는 $1로 옮겨간다.

#!/bin/bash
count=1
while [ -n "$1" ]; do
    echo "Parameter #$count = $1"
    count=$[ $count + 1 ]
    shift
done

 

shift에 매개변수로 이동시키고 싶은 만큼의 자릿수를 사용할 수도 있다.

 

옵션 처리하기

위에 기술한 것들을 바탕으로 옵션을 처리하는 쉘 스크립트를 짤 수도 있다.

#!/bin/bash

while [ -n "$1" ]; do
    case "$1" in
    -a) echo "Found -a option" ;;
    -b) echo "Found -b option" ;;
    -c) echo "Found -c option" ;;
    --) shift
        break ;;
    *) echo "$1 is not an option" ;;
    esac
    shift
 done

 

위의 쉘 스크립트는 ./test.sh -a -b -c test1 test2 test3로 실행했을 때 -a, -b, -c 까지는 옵션으로 인식하고

나머지는 매개변수로 인식한다.

 

getopt 명령 사용하기

getopt 명령은 getopt optstring parameters 와 같은 형식으로 사용한다.

getopt ab:cd -a -b test1 -cd test2 test3

 

위의 예시에서 a, b, c, d가 유효한 옵션 문자로 설정되었고 b뒤에는 콜론이 붙어있으므로 매개변수가 필요함을 의미한다.

또한 -cd는 -c -d로 분리해서 인식한다.

 

스크립트에서 getopt를 사용하기 위해서는 set 명령을 사용한다.

set 명령의 옵션 중 하나는 이중 대시로, 이중 대시는 set 명령에게 커맨드라인 매개변수를 대체하게 할 수 있다.

#!/bin/bash
set -- $(getopt -q ab:cd "$@")
while [ -n "$1" ]; do
    case "$1" in
    -a) echo "Found -a option" ;;
    -b) param="$2"
        echo "Found -b option, param value: $param"
        shift ;;
    -c) echo "Found -c option" ;;
    --) shift
    	break ;;
    *) echo "$1 is not an option" ;;
    esac
    shift
done

count=1
for param in "$@"; do
    echo "Parameter #$count: $param"
    count=$[ $count + 1 ]
done

 

다만 getopt의 문제점은 따옴표안에 있는 빈 칸도 매개변수 구분자로 해석한다는 문제점이 존재한다.

이를 해결하기 위해서는 getops를 사용해야 하는데, 본 포스팅에서는 이를 다루지 않는다.

 

다음은 리눅스에서 널리 쓰이는 커맨드라인 옵션이다.

옵션 설명
-a 모든 개체 표시
-c 카운트를 만든다
-d 디렉토리를 지정한다
-e 개체를 확장한다
-f 데이터를 읽기 위해 파일을 지정한다
-h 명령에 대한 도움말을 표시한다
-i 텍스트의 대소문자를 무시한다
-l 출력의 긴 형식 버전을 만든다
-n 비대화형 모드를 사용한다
-o 모든 출력을 리다이렉트할 출력 파일을 지정한다
-q 침묵 기록 모드에서 실행된다
-r 디렉토리와 파일을 재귀적으로 처리한다
-v 상세한 출력을 만든다
-x 개체를 제외한다
-y 모든 질문에 yes로 답한다

 

사용자 입력 받기 

read 명령은 표준 입력은 또는 다른 파일 디스크립터에서 입력을 읽어들이고 변수에 저장한다.

다음은 read 명령의 가장 기초적인 사용방법이다.

#!/bin/bash
echo -n "Enter your name: "
read name
echo "Hello $name, welcome!"

 

read 명령은 -p 옵션을 사용해서 커맨드라인에 직접 메세지를 지정할 수 있다.

#!/bin/bash
read -p "Enter your name: " first last
"Your first name is $first, last name is $last"

 

또는 read 커맨드라인에 어떤 변수가 지정하지 않을 수 있는데, 이런 경우 $REPLY에 받은 모든 데이터를 저장한다.

 

-t 옵션을 사용해서 타이머를 지정할 수 있는데, 타이머가 만료되면 read 명령은 0이 아닌 종료 상태를 돌려준다.

비밀번호와 같이 화면에 표시하면 안되는 데이터는 -s 옵션을 사용한다.

 

read 명령을 통해 파일에서 데이터를 읽어들일 수도 있는데, 보통 파일의 cat 명령 결과를 파이프를 통해

곧바로 read 명령을 가지고 있는 while 명령에 전달한다. 다음은 그 예시이다.

#!/bin/bash
count=1
cat testfile | while read line
do
    echo "Line $count: $line"
    count=$[ $count + 1 ]
done
echo "Finished processing the file"