rcmdnk's blog

Mastering Linux Shell Scripting: A practical guide to Linux command-line, Bash scripting, and Shell programming, 2nd Edition

ちょっと勘違いしてしばらく悩んだ話。

シェルスクリプトの引数

シェルスクリプトを書いている時に、引数をチェックするために

test.sh
1
2
#!/usr/bin/env bash
echo "$@"

みたいなことをして引数をチェックしていたら-e-nが消えている? とわからなくなってちょっと試してみると

1
2
3
4
5
6
7
8
9
10
11
12
$ for v in a b e f g n u v w x y z;do ./test.sh -$v XXX;done
-a XXX
-b XXX
XXX
-f XXX
-g XXX
XXX-u XXX
-v XXX
-w XXX
-x XXX
-y XXX
-z XXX

起こっている情況としては、

  • -eが消えている
  • -nも消えている。かつ改行がなくなって次の-uが同じ行に出力されている。

という状態。

シェルスクリプトにこんな仕様があるのかとちょっと検索しても出てこなくて ChatGPTに聞いたら -eset -eerrexitのオプション、-nset -nnoexecのオプションだからそうなっているし、 正しくはスクリプトの中でset -eとかしなさい、とのこと。

でもよく使う-u(nnounset)や-a(allexport)とかも同様では?

また、

1
2
$ ./test.sh -a XXX -e YYY
-a XXX -e YYY

と最初に来なければ見えている状態。

さらに、

test2.sh
1
2
#!/usr/bin/env bash
echo INPUT="$@"

とすると、

1
2
$ ./test2.sh -e XXX
INPUT=-e XXX

見えた。。。

echoの引数なだけ

勘違いしてたのは単にechoのオプションとして-eがbackslashによるエスケープシーケンスをを有効にするオプションで、-nが最後を改行なしにするオプション、というだけ。

$@で渡しているので一つ一つ分けて順にechoに渡されるわけで、最初に-e-nが渡されればオプションとして使われていただけです。

エスケープシーケンスなどはないので-eが渡されれば単にそのオプション分は表示されず、 -nが渡されれば-nはオプションとして消化されて表示されずさらに改行なしになるだけです。

なので$@自体にはこれらはちゃんと入ってますし使えます。

BSDなecho

BSDな/bin/echo-eオプションが無いので、macOSとかで

test3.sh
1
2
#!/usr/bin/env bash
/bin/echo "$@"

というスクリプトを作ると

1
2
3
4
5
6
7
8
9
10
11
12
$ for v in a b e f g n u v w x y z;do ./test3.sh -$v XXX;done
-a XXX
-b XXX
-e XXX
-f XXX
-g XXX
XXX-u XXX
-v XXX
-w XXX
-x XXX
-y XXX
-z XXX

と、-eでも通常通り表示されます。

macOSでも普通にecho使うとbashのbuiltinなechoが使われるので-eは有効で消えます。

1
2
3
$ type -a echo
echo is a shell builtin
echo is /bin/echo
Sponsored Links
Sponsored Links

« シェルスクリプトでスクリプトの引数をループする方法 シェルスクリプトで二重括弧による計算を行う際の0Xな数字に関する注意 »

}