はじめに
シェルのワンライナーでなるべく簡単に同じ文字または同じ文字列を指定した回数繰り返した文字列を作る方法です。
条件
- 出力の行末にはちゃんと改行をつける
- POSIX で標準化された機能のみで作る
-
head
コマンドは使わない(理由は後述)
基本: printfでn文字のスペース文字列を作る
まずすべてに共通する基本のコードとして n 文字のスペース文字列を作る方法です。printf
コマンドの書式の末尾に改行があることに注意してください。
$ printf '%10s\n'
スペースだと分かりづらいと思う場合は代わりに 0 を使用する方法もありますが、BusyBox ashでは引数の 0 を省略するとエラーになってしまうため移植性が必要な場合は引数が必要です。その結果、少し長くなってしまいます。
$ printf '%010d\n' 0
0000000000
$ busybox ash -c 'printf "%010d\n"'
ash: invalid number ''
0000000000
変数 n
で長さを指定したい場合には次のようにします。
$ printf "%${n}s\n"
$ printf '%*s\n' "$n"
繰り返しの数をスペースの数で表現することに気がつけば、いろんなものに応用することができます。
同じ文字を繰り返した文字列を作る
同じ文字の繰り返しを作る方法です。tr
コマンドを利用します。
$ printf '%10s\n' | tr ' ' =
==========
同じ文字列を繰り返した文字列を作る
同じ文字列(2文字以上の文字)の繰り返しを作る方法です。sed
コマンドを利用します。
$ printf '%5s\n' | sed 's/ /=+/g'
=+=+=+=+=+
ちょっとした応用ですが、このようにすれば最初と最後の文字を同じにすることができます。デザインに凝りたい場合に使えるでしょう。
$ printf '%9s\n' | sed -e :a -e 's/ /=/; s/ /+/; ta'
=+=+=+=+=
同じ文字列を縦にn個繰り返す
縦に繰り返す方法です。printf
コマンドの書式の末尾に改行がないことに注意してください。
$ printf '%5s' | tr ' ' '\n' | sed 's/^/===/'
===
===
===
===
===
GNU sed や最近の BSD 系の sed
に限られますが、次のような書き方もできます。
$ printf '%5s' | sed 's/ /===\n/g'
===
===
===
===
===
なぜhead -n Nを使わないのか?
出力の個数を制限する場合、head
コマンドを使うことを思いつくかもしれませんが、head -n N
を使用すると SIGPIPE
のエラーが(内部的に)発生することがあります。そのため無限に出力して数を制限するよりも、出力の数を制限したほうが良いです。
$ set -o pipefail
$ yes === | head -n 5
===
===
===
===
===
$ echo $?
141
$ kill -l 141
PIPE
さいごに
他にもいろいろやり方はあると思いますが、シンプルで移植性が高いという点ではこんなところではないかと思います。ブレース展開が POSIX で標準化されると良いんですけどね。
その他の方法(POSIXで標準化されていない拡張機能を使った方法)についてはこちらへ