2013年6月9日日曜日

bashのsequence expressionをfor文で使おうとしたら

bashにsequence expressionというものがあります。
例えば、{1..5}と書くと1 2 3 4 5に展開されます。
$ echo {1..5}
1 2 3 4 5
ファイル名の一部に連番がある場合にファイル名の生成に使ったり、for文の範囲指定に使えます。
例えば、
for i in {1..5}; do
  echo $i
done
と書くと、実行結果は
1
2
3
4
5
となります。ところが、範囲指定のどちらかに変数になっていると期待通りにはなりません。
N=5
for i in {1..$N}; do
  echo $i
done
では、結果は
{1..5}
となって、sequence expressionが表示されます。ブレース展開({}を用いた式の展開)は、bashの実行の最初期に行われ、その後変数展開が行われるためとのことです。
どうしても使いたい場合は、以下のように{1..5}となる部分をもう一度評価する必要があります。

N=5
for i in `eval echo {1..$N}`; do
  echo $i
done
の実行結果は
1
2
3
4
5
となります。最初に考えた{1..$N}より随分長くなってしまいます。これなら、以前のseqコマンドを使った書き方の

N=5
for i in `seq 1 $N`; do
  echo $i
done

が短いですね。
seqは外部コマンドで、eval, echoはbashの内部コマンドなので多少evalの方が軽いかもしれませんが、使う状況を考えるとseqのままで良さそうです。

0 件のコメント:

コメントを投稿