Positional Parameters

  • 스크립트 파일을 실행할 때
  • function 을 호출할 때
  • 스크립트 파일을 source 할 때

인수를 주게되면 해당 스크립트 및 함수 내에서 positional paramters 가 자동으로 설정됩니다. 첫번째 인수는 $1 , 두번째는 $2 ... 식으로 할당되며 scope 은 local 변수와 같습니다. sh 과 같이 array 를 사용할 수 없는 환경에서 활용할 수 있습니다.

$0

스크립트 파일 이름를 나타냅니다.

$ cat test.sh
#!/bin/sh

echo \$0 : $0
echo \$1 : $1
echo \$2 : $2
.................

$ ./test.sh 11 22
$0 : ./test.sh
$1 : 11
$2 : 22
-----------------

# shell 함수는 $0 값이 /bin/bash 가 된다.
$ testfunc() { echo \$0 : $0; echo \$1 : $1; echo \$2 : $2; }

$ testfunc 11 22
$0 : /bin/bash       
$1 : 11
$2 : 22

sh -c 형식으로 실행했을 경우는 첫번째 인수를 가리킵니다.

$ sh -c 'echo $0, $1, $2' 11 22 33
11, 22, 33

프롬프트 에서 사용할 경우

$ echo $0
/bin/bash

$ $0 --version
GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)
...

어떤 명령을 다른 이름으로 symbolic link (또는 hard link) 한 후 링크 이름으로 실행을 하면 $0 값이 링크 이름 됩니다.

$ cat ccache.sh
#!/bin/sh

echo "Im running '$0'"
---------------------------

$ chmod +x ccache.sh

$ ./ccache.sh
Im running './ccache.sh'

$ ln -s ccache.sh gcc.sh

$ ./gcc.sh
Im running './gcc.sh'

$ ln -s ccache.sh clang.sh

$ ./clang.sh
Im running './clang.sh'

$1, $2, $3 ...

각 인수들을 나타냅니다.

--------- test.sh --------
#!/bin/sh

echo number of arguments = $#

echo \$0 = "$0"

echo \$1 = "$1"
echo \$2 = "$2"
echo \$3 = "$3"


######### output ########

$ ./test.sh 11 22 33
number of arguments = 3
$0 = ./test.sh
$1 = 11
$2 = 22
$3 = 33

$#

$0 을 제외한 전체 인수의 개수를 나타냅니다.

$ cat test.sh
#!/bin/sh

echo $#
.....................

$ ./test.sh 11 22 33
3

$ set --

$ ./test.sh "$@"
0
$ ./test.sh "$*"    # "" 이 인수로 잡힌다.
1

$@ , $*

$@, $* 는 positional parameters 전부를 포함합니다. array 에서 사용되는 @ , * 기호와 의미가 같다고 볼 수 있습니다. 변수를 quote 하지 않으면 단어분리에 의해 두 변수의 차이가 없지만 quote 을 하게 되면 "$@" 의 의미는 "$1" "$2" "$3" ... 와 같게되고 "$*" 의 의미는 "$1c$2c$3 ... " 와 같게됩니다. ( 여기서 cIFS 변수값의 첫번째 문자 입니다. )

--------- test.sh --------
#!/bin/sh

echo \$@ : $@
echo \$* : $*

echo '======== "$@" ======='
for v in "$@"; do             # 또는 for v do ...
    echo "$v"
done

echo '======== "$*" ======='
for v in "$*"; do
    echo "$v"
done

########### output ##########

$ ./test.sh 11 22 33
$@ : 11 22 33
$* : 11 22 33
======== "$@" =======
11
22
33
======== "$*" =======
11 22 33

-----------------------------

$ f1() { "$@" ;}
$ f1 date +%D
01/22/16

$ f1() { "$*" ;}
$ f1 date +%D
date +%D: command not found   # 'date +%D' 가 명령 이름이 된다.

"$*" 는 항상 IFS 변수값의 첫번째 문자를 인수 구분자로 갖습니다.

$ set -- 11 22 33 44 55

$ IFS=XYZ
$ echo "$*" , $*
11X22X33X44X55 , 11 22 33 44 55

$ IFS=YZ
$ echo "$*" , $*
11Y22Y33Y44Y55 , 11 22 33 44 55

$ IFS=:
$ echo "$*" , $*
11:22:33:44:55 , 11 22 33 44 55

set

set 명령은 보통 shell 옵션을 설정할때 사용하지만 positional paramters 를 설정하거나 삭제할때도 사용됩니다. 다음 3가지 방법은 11 22 33 을 각각 $1 $2 $3 positional parameters 에 할당합니다.

$ set 11 22 33
$ set - 11 22 33
$ set -- 11 22 33
$ echo $1 $2 $3
11 22 33

# 'set --' 은 현재 설정되어 있는 positional parameters 를 모두 삭제합니다.
$ set --
$ echo $1 $2 $3
$

사용예 )

--------- test.sh --------
#!/bin/sh

# set 명령을 이용하여 script 내에서 positional parameters 를 설정
set -- 11 22 33        

echo number of arguments = $#

echo \$0 = "$0"

echo \$1 = "$1"
echo \$2 = "$2"
echo \$3 = "$3"

######### output ########

$ ./test.sh
number of arguments = 3
$0 = ./test.sh
$1 = 11
$2 = 22
$3 = 33

--------- set 활용 --------

$ date
Sat Dec 31 07:45:56 KST 2016

$ set -- $(date)

$ echo 오늘은 $2$3$1 요일 $4 시 입니다.
오늘은 Dec 월 31 일 Sat 요일 07:46:29 시 입니다.

shift

shift [n]

shift 명령은 현재 설정되어 있는 positional parameters 를 좌측으로 n 만큼 이동시킵니다.
결과로 n 개의 positional parameters 가 삭제 됩니다.

$ set -- 11 22 33 44 55

$ echo $@
11 22 33 44 55

$ shift 2

$ echo $@
33 44 55

$IFS

$IFS 변수와 set 명령을 이용하여 스트링에서 필드를 분리해낼 수 있습니다.

#!/bin/sh

line="11:22:33:44:55"

set -f; IFS=:        # globbing 을 disable
set -- $line         # IFS 값에 따라 필드를 분리하여 positional parameters 에 할당
set +f; IFS=`echo " \n\t"`

echo number of fields = $#
echo field 1 = "$1"
echo field 2 = "$2"

shift 3
echo \$@ = "$@"

############# output #############

number of fields = 5
field 1 = 11
field 2 = 22
$@ = 44 55

Substring expansion

Substring expansion 은 bash 에서만 사용할수 있습니다.

$ set -- 11 22 33 44 55

$ echo ${@:3}
33 44 55

$ echo ${@:2:2}
22 33