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

2023-02-13Bash

はじめに

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

ここでは、任意の文字列として = を使用し、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
==========

方法 5. xargs を使う

[2023-02-13] ありがたいことにコメントを頂きましたので紹介します

xargs を使っても実現できます。

$ seq 10 | xargs -i echo -n =
==========

$ seq 10 | xargs -i echo -n Hello
HelloHelloHelloHelloHelloHelloHelloHelloHelloHello

実現方法が素直で良いですね。

ひとこと

個人的には ( 2 ) または ( 3 ) の方法がわかりやすく好みです。

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

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

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

2023-02-13Bash