ETC

유용한 쉘 스크립트 문법

kahuz 2021. 6. 5. 04:01

유용한 쉘 스크립트 문법

리눅스 환경에서 개발을 하다보면 다양한 이유로 쉘 스크립트를 사용하게 됩니다. 가장 흔한 이유는 빌드의 자동화 혹은 특정 어플리케이션 실행의 편의성을 높이기 위함입니다.

 

예를 들어 my_app 이라는 어플리케이션의 입력 변수로 -debug_level={1~4} 라는 옵션과 -detect_object={ cat, dog, people} 같은 옵션을 준다고 예를 들어보겠습니다.

 

이 경우 일일이 해당 옵션을 수정하는건 개발자에게 너무 큰 고욕임이 확실합니다. 따라서 아래와 같은 쉘 스크립트를 이용하면 보다 편리하게 앱을 실행시키고 디버깅 혹은 테스트를 할 수 있게 됩니다.

 

#!/bin/bash
APP="my_app"
OPT1="-debug_level"
OPT2="-detect_object"

if [ $# -eq 0 ] 
then
    echo "default mode select!"
    echo "./$APP $OPT1=1 $OPT2=cat"
elif [ $# -eq 1 ] 
then
    echo "input debug_level=$1"
    #echo "./$APP $OPT1=$1 $OPT2=cat"
    ./$APP $OPT1=$1 $OPT2=cat
else
    echo "input debug_level=$1 detect_object=$2"
    #echo "./$APP $OPT1=$1 $OPT2=$2"
    ./$APP $OPT1=$1 $OPT2=$2
fi

위 스크립트의 키포인트는 아래와 같습니다.

  • if, elif, else, fi
    • 일반적인 프로그래밍 언어와 같은 if, else 구문을 위한 키워드 입니다.
    • if와 elif는 if의 키워드로써 if [ 조건 ] then 실행구문 fi 로 구성됩니다
  • $# ,$1, $2
    • $#은 입력 파라메터의 개수, $0 .... $N 은 입력된 순번의 파라메터를 의미합니다.
    • $0는 실행 스크립트의 이름입니다.
  • -eq , -ne , ==
    • eq 는 equal , ne는 not equal 으로 쓰입니다.
    • if 문에서 A -eq B , A -ne B 와 같은 형태로 쓰일 수 있습니다.
    • 문자열의 경우 "A" == "B" 와 같이 사용할 수 있습니다.

 

이 외에도 아래와 같은 빌드 스크립트를 만들 수 있습니다.

#!/bin/bash

ARG1=""
APP="app*"
PROJ=""

if [ $# -eq 0 ]
then
    echo "input command"
    exit 0
else
    ARG1="$1"
fi
# clean all binary files
if [ "$ARG1" == "clean" ]
then
    rm -f $APP
    exit 0
# if exist the $1.c file,
elif [ "${ARG1##*.}" == "c" ]
then
    PROJ=$ARG1
    APP="app_${ARG1:0:-2}"
    gcc ${PROJ} -o ${APP} `pkg-config --cflags --libs gstreamer-1.0`
# or, exist the $1.cpp file
elif [ "${ARG1##*.}" == "cpp" ]
then
    PROJ=$ARG1
    APP="app_${ARG1:0:-4}"
    g++ ${PROJ} -o ${APP} `pkg-config --cflags --libs gstreamer-1.0`
else
    echo "input compile file name"
    echo "${ARG1##*.}"
    exit 0
fi

echo "compile ${PROJ}"
echo "create ${APP}"

위 스크립트에 대해 간단히 설명하면 ./script test.c 와 같이 입력하였을 때, 입력된 test.c 가 c 파일 혹은 cpp 파일인지 검사하여 gcc 혹은 g++을 호출한 뒤 app_test 바이너리를 생성하는 스크립트입니다.

 

굳이 CMake나 Make 같은 빌드 시스템이 있는데 이렇게 쓸 필요가...? 라고 할 수 있지만 다양한 방법을 알아둬서 나쁠 건 없다 라는게 개인적인 생각입니다.

 

사실 같은 라이브러리를 공유하는 단일 모듈 프로그램을 테스트할 때 위 스크립트를 이용하면 CMake나 Make 파일을 고치는 행위도 필요없기도 하며, 입력 변수로 파일 이름만 던져주면 되기에 저런 식으로 사용하였습니다.

 

다시 글의 요점으로 돌아와, 위 스크립트의 키포인트는 "${ARG1##*.}" 입니다.

"${ARG1##*.}" 에서 ##은 앞의 ARG1 로부터 *. 와 일치하는 문자열을 제거한다는 의미를 가집니다.

더욱 간단한 예로 ABCD##A 의 리턴 값은 BCD가 됩니다.

다만 주의할 점으로 ABCD##BC 의 경우 리턴 값은 ABCD 입니다. {A}##{B}으로 문자열을 조회할 때 {B} 에 해당하는 문자열의 가장 앞 부분과 {A} 문자열의 가장 앞부분부터 동일한지 확인한 뒤 제거하기 때문입니다.

 

이 외에도 쉘 스크립트에서는 시스템 명령어를 그대로 활용할 수 있기에 간단한 자동화 스크립트를 생성하여 작업의 효율을 크게 상승 시킬 수 있습니다.

'ETC' 카테고리의 다른 글

윈도우 환경에서 VS Code + CMake 환경 구성하기  (0) 2022.02.28