🕌
シェルスクリプトのprintfで引数を使い回したい
やりたいこと
printf '%s %s' a
で
a a
のように表示したいです(実際に実行すると、これはa
になります)。
なぜ、これをやりたいかと言うと、
- 同じようなクエリを複数のテーブルに投げるシェルスクリプトが欲しい
- この仕組み自体はループとprintf組み合わせればすぐ
- クエリ内でテーブルの名前を複数回参照したい時がある
- クエリ内での参照が一回の時も、二回・三回の時も対応できると嬉しい
場合があったためです。
# hoge.shの中で処理対象のテーブル毎にクエリを実行。%sの部分に処理対象のテーブルを入れたい
# どのテーブルに対するクエリかわかるように、クエリ結果にテーブル名を入れたい場合もある
./hoge.sh 'SELECT "%s", id FROM %s'
zsh
zsh builtinのprintfの場合は簡単で、何番目の引数か指定するフォーマット(%n)があります。
Normally, conversion specifications are applied to each argument in order but they can explicitly specify the nth argument is to be used by replacing ‘%’ by ‘%n
’. It is recommended that you do not mix references of this explicit style with the normal style and the handling of such mixed styles may be subject to future change. ’ and ‘*’ by ‘*n
それを利用することで、今回やりたい処理を行うことができます。
# zsh
printf '%1$s %1$s' a
a a
zshのprintfを使いたい場合
- printfのフォーマット内の%sの数を数える
- その数の個数だけ、フォーマットに入れたい文字列を引数に渡す
で対応できそうです。
フォーマット($fmt)内の%sを数えるのはgrep -o(マッチした部分を新たな行で表示)とwcコマンドで出来ます。
echo $fmt | grep -o '%s' | wc -l
同じ文字列を繰り返すには、yesとhead
yes "繰り返したい文字列" | head -n $(echo $fmt | grep -o '%s' | wc -l)
xargsでprintfで渡して完成です
yes "繰り返したい文字列" | head -n $(echo $fmt | grep -o '%s' | wc -l) | xargs printf $fmt
SELECT "繰り返したい文字列",id FROM 繰り返したい文字列
Discussion