Help us understand the problem. What is going on with this article?

コマンドの引数内で変数を扱う際に気をつけること

More than 5 years have passed since last update.

スクリプトを書いていて,コマンドの引数やら,awkのスクリプトやらにシェルの変数を用いることはほんっとーによくあることだと思います.まず先に結論をいうと,

"変数展開に気をつけろ"

ということです.
この先を見てもらえれば当たり前の話じゃねーかよって感じで恐縮ですが,なんどもこいつでつまずいてるので,自分を戒めるためにメモ.

自分がはまっていた具体例をまず出します.awkの正規表現中にシェルの変数を用いる,というものです.これはawkスクリプトを「'」か「"」のいずれかで囲った場合に分けて,次のように記述できます.

ptn="foo"
echo "foo bar" | awk '/'${ptn}'/{print $0}'
#または
echo "foo bar" | awk '/'''${ptn}'''/{print $0}'
ptn="foo"
echo "foo bar" | awk "/${ptn}/{print \$0}"
#または
echo "foo bar" | awk "/"""${ptn}"""/{print \$0}"

トリプルクォートは調べてたら見つかったのでおまけです(用途がいまいちピンとこないので教えていただければ喜びます).けれどもこやつら,完璧ではありません.この渡し方では上記の変数hogeに空白が含まれている場合,構文エラーとなってしまいます.なので,以下のように記述すれば空白を含む変数に対しても有効となります.

ptn="foo bar"
# OK
echo "hoge foo bar" | awk '/'"${ptn}"'/{print $0}'
# ERROR
echo "hoge foo bar" | awk '/'${ptn}'/{print $0}'

じゃあ先の記述だとなにがいけないのか.肝となるのはシェルの変数展開です.変数を「"」でくくるか否かで,評価が変わります.

hoge="hoge foo bar"
${hoge}   -> "hoge" "foo" "bar"
"${hoge}" -> "hoge foo bar"

変数には1つの文字列が格納されているにも関わらず,展開すると空白を区切り文字として複数の文字列に置き換わってしまいます.例えばこれをtouchコマンドの引数にとれば,前者ではhoge,foo,barの3つのファイルができ,後者では"hoge foo bar"という1つのファイルが出来るというわけです.

つまり先のawkの例では以下のように評価されます.

ptn="foo bar"
# OK
awk '/'"${ptn}"'/{print $0}' -> awk '/foo bar/{print $0}'
# ERROR
awk '/'${ptn}'/{print $0}'   -> awk '/foo' 'bar/{print $0}'

こういうわけで,”変数展開には気をつけろ”です.以上,当たり前な話でした.

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away