태그 보관물: bash

shell 파라미터 치환

${ 파라미터 }

${Parameter}$Parameter와 같은 표현으로 주로 붙여쓴 경우에 구분을 위해서 사용하는 표기로 알려져 있다.

your_id=${USER}-on-${HOSTNAME}
echo "$your_id"
#
echo "Old \$PATH = $PATH" 
PATH=${PATH}:/opt/bin
echo "New \$PATH = $PATH"

${ 파라미터-디폴트}, ${파라미터:-디폴트}

파라미터가 정의되지 않았다면 디폴트값을 쓸 수 있게 해준다.

var1=1
var2=2
# var3 is not defined
echo ${var1-$var2} # 1
echo ${var3-$var2} # 2

echo ${username-`whoami`} # username이 정의되지 않았다면 `whoami`의 결과를 출력한다.

-, :- 의 차이는 별로 없다. 다만 - 는 변수이름자체가 정의되지 않았을 때 동작하며, :- 는 값이 null 일 때도 동작한다.

username0=     # null
# username1, username2 는 선언조차 되지 않음
echo ${username0-`whoami`} # 프린트 되지 않는다.
echo ${username1-`whoami`} # 프린트 된다.
echo ${username2-`whoami`} # 프린트 된다.

echo ${username0:-`whoami`} # 프린트 된다.
#               ^
echo ${username1:-`whoami`} # 프린트 된다.
echo ${username2:-`whoami`} # 프린트 된다.


이는 흔히 스크립트 내에서 인자가 생략되었을 경우 디폴트 값을 쓰는 데 쓰인다.

#!/usr/bin/bash
# add.sh
x=$((${1-1}+${2-2}))
echo $x

그리고 다음과 같이 쓴다.

$ add.sh 30 40
70
$ add.sh 30
32
$ add.sh
3

${파라미터=디폴트}, ${파라미터:=디폴트}

${-} 는 없는 변수에 대해 그 값만 디폴트를 취하는 것인데, 이 표현은 변수가 없거나 null 값이면 (:=의 경우) 즉석에서 해당 변수를 정의한다. 따라서 해당 문맥 이후에는 내부에서 정의한 변수값을 계속 사용할 수 있게 된다.

$ echo ${var=abc} # abc
$ echo ${var=xyz} # abc
$ echo $var # abc

${파라미터+대체값}, ${파라미터:+대체값}

잘 쓰이지는 않을 것 같은데 :-의 반대 표현이다. 선언되었고 값이 정의되어 있는 경우에만 대체값이 쓰인다. 그렇지 않은 경우 널스트링이다. :+의 경우에는 선언은되었으나 값이 널인 경우만 대체값을 쓴다.

${파라미터?에러메시지}, ${파라미터:?에러메시지}

파라미터가 있으면 그 값을 쓴다. 그렇지 않은 경우에는 에러메지시를 표시하고 리턴 코드 1을 내며 스크립트를 즉시 종료한다.

${#변수}

변수를 확장했을 때 문자의 길이가 된다. 배열인 경우에는 첫번째 원소의 길이가 된다.

$ x="hello world"
$ echo ${#x}
11
$ y=(hello world)
$ echo ${#y}
5 # hello

${변수#패턴}, \${변수##패턴}

변수를 확장한 값에 대해서 패턴과 매치되는 최소(#), 최대(##) 매칭을 제거한다.

# current directory
echo $PWD  # 전체 경로 출력
echo ${PWD##*/} # 디렉토리 이름만
filename=hello.txt
ext=${filename##*.} # txt

${변수%패턴}, ${변수%%패턴}

변수의 값에 대해서 패턴과 매치되는 맨 뒤쪽 끝 매칭을 제거한다. % 는 최소, %%는 최대이다.

var1=abcd12345abc6789
pattern1=a*c

echo
echo "var1 = $var1"
echo "var1 = ${var1}"

echo "Number of characters in ${var1} = ${#var1}"
echo

echo "pattern1 = $pattern1"
echo "----------------"
echo '${var1#$pattern1} =' "${var1#$pattern1}" # abcd12345abc6789
#                                         |-|
# d12345abc6789
echo '${var1##$pattern1} =' "${var1##$pattern1}" # abcd12345abc6789
#                                           |----------|
# 6789
echo;echo;echo

pattern2=b*9
echo "var1 = $var1"
echo
echo "pattern2 = $pattern2"
echo "--------------"
echo '${var1%$pattern2} = ' "${var1%$pattern2}" # abcd12345abc6789
#                                                        |----|
# abcd12345a
echo '${var1%%$pattern2} = ' "${var1%%$pattern2}"   # abcd12345abc6789
#                                              |-------------|
# a

다음은 이를 활용한 확장자 변경 스크립트 (이름만 바꾼다.)

#!/bin/bash

E_BADARGS=65

case $# in
  0|1)     # 인자의 개수가 0, 1개인 경우,
  echo "Usage: `basename $0` old_file_suffix new_file_suffix"
  exit $E_BADARGS
esac

for filename in *.$1
do
    mv $filename ${filename%$1}$2
done

exit 0

그외 몇 가지 더…

  • ${var:pos} : 주어진 위치부터 끝까지
  • ${var:pos:len} : 중간 슬라이스
  • ${var/pattern/replacement}: 패턴에 일치하는 부분을 치환한다.
  • ${var//pattern/replacement} : 패턴에 일치하는 부분 전체를 치환한다.
  • ${var/#pattern/replacement} : 패턴에 일치하는 부분을 맨 앞 한군데만 치환한다. (맨 첫 시작부터 매칭해야 함)
  • ${var/%pattern/replacement} : 패턴에 일치하는 부분을 맨 뒤 한군데만 치환한다. (맨 끝부분이 정확히 일치해야 함)
  • ${!varprefix*}, ${!varprefix@} : 변수이름이 접두사와 매칭하는 전체 변수값들을 가져온다.

shell – expansion

셸 스크립트를 사용하면서, 가장 헷갈리는 부분 중 하나가 문자열 값들이 어떻게 확장되는가 하는 점이다. 여기서는 조금 자세하게 엔터키를 누르는 그 순간에 어떤 ‘마법’이 벌어지는지 보려고한다. 몇 가지 간단한 예제들에서도 이 현상은 우리가 알지 못하는 사이에 쓰고 있는 셈인데, 이를테면 echo 같은 명령에서 이것이 일어난다.

확장 (expansion)

명령을 입력하고 엔터를 누르는 매 순간에 bash는 우리의 명령을 수행하기 이전에 몇 가지 텍스트 관련 처리를 먼저 하게 된다. 이미 echo * 등의 명령에서 어떻게 단순한 글자가 변경되는지를 본 적이 있다. 예를 들어 *는 쉘에서 여러가지 의미를 가지게 된다. 이것이 실제로 벌어지는 것을 우리는 확장(expansion)이라 부른다. 확장을 통해 우리가 무언가를 입력하고, 그것은 다시 다른 무언가로 확장된 후, 실제 명령은 그것을 통해 수행된다. 이를 들여다보기 위해 echo 명령을 좀 더 살펴보자. 이는 아주 단순한 빌트인 명령으로 그저 텍스트를 화면에 출력한다.

$ echo this is a test
this is a test

간단하다. 넘겨지는 모든 인자가 출력된다. 다음은 어떤가?

$ echo *
Desktop Document ls-output.txt Music Pictures Public Templates Videos

Continue reading “shell – expansion” »