Bashシェルスクリプトで任意の文字を繰り返し出力する方法

2020-11-18Bash

はじめに

検証のために特定の文字列を繰り返し出力したかったのですが、どうするのがよいか悩んだため思いついた方法をいくつか共有します。

ここでは、任意の文字列として = を使用し、10文字出力してみたいと思います。

検証環境

$ uname -moi
x86_64 MacBookPro16,1 Darwin

$ bash -version | head -n 1
GNU bash, バージョン 5.0.18(1)-release (x86_64-apple-darwin19.5.0)

方法1. printf コマンドを使う方法

printf を使ってこれを実現する事ができます。

$ printf "=%0.s" {0..9}
==========

いきなり見ただけでは少々わかりにくいと思います。
以下のように置き直すとわかりやすいと思います。

$ printf "=%0.s" 0 1 2 3 4 5 6 7 8 9
==========

printf のオプションを変えたコマンドの実行結果と比較するとよりわかりやすいでしょう。

$ printf "=%s" {0..9}
=0=1=2=3=4=5=6=7=8=9

printf の引数が "=%s" コマンドを実行した結果は、= と第2引数以降の値が繰り返し出力されています。
printf の引数が "=%.0s" コマンドを実行した結果は、= だけが繰り返し出力され、第2引数そのものは出力されません。
この仕組を利用した文字列の繰り返し出力方法となっています。

応用して、 Hello という文字列を5回出力してみます。

$ printf "Hello%.0s" {0..4}
HelloHelloHelloHelloHello

方法2. yes コマンドを使う方法

printf コマンドを使う方法よりもコマンドが面倒になりますが、僕はこの方法のほうが直感的でわかりやすいので好きです。

yes コマンドを使った方法です。

$ yes = | head -n 10 | tr -d '\n'
==========

yes コマンドは、引数で渡された文字列を浸すら出力し続けるコマンドです。
挙動を知りたければ、 yes = だけを実行してみると良いでしょう。( 止めたいときは CTRL+C を押してください。 )

$ yes =
=
=
=
=
=
...(省略)

ひたすら = が出力されますね。
この出力内容を head コマンドにパイプで渡します。
ここでは 10行分 だけ出力させています。

$ yes = | head -n 10
=
=
=
=
=
=
=
=
=
=

更にこれを tr コマンドにパイプで渡します。
改行を取り除くことで、 = が10文字連結された内容となります。

応用して、 Hello という文字列を5回出力してみます。

$ yes Hello | head -n 5 | tr -d '\n'
HelloHelloHelloHelloHello

方法3. seq コマンドを使う方法

こちらは yes コマンドを使う方法よりも短いです。
実行コマンドも2つだけですし、シンプルです。

seq 0 10 で、 0から10までの数値が改行区切りで出力されます が、 -s "=" というオプションを付与することで区切り文字を改行から = という文字に変更することができます。

$ seq -s '=' 0 10
0=1=2=3=4=5=6=7=8=9=10

その出力内容から数字を除去すれば完成です。

$ seq -s '=' 0 10 | tr -d '[0-9]'
==========

もちろん Hello を5回繰り返す事もできます。が

$ seq -s 'Hello' 0 5 | tr -d '[0-9]'
HelloHelloHelloHelloHello

ただし、 繰り返し文字列に数値が含まれていた場合はこの方法では問題がおきること に注意が必要です。

方法4. for でループする

難しいことを考えずにループしてしまう方法です。

$ for ((i=0; i<10; i++)); do
    echo -n '='
  done
==========

ひとこと

個人的には (2) または (3) の方法がわかりやすいし覚えやすいしで好きです。

ちなみに実行結果を変数に保存するには以下のようなコマンドを実行します。

$ BAR=$(yes '=' | head -n 10 | tr -d '\n')

$ echo $BAR
==========

2020-11-18Bash