LoginSignup
5
5

More than 1 year has passed since last update.

bash シェルで<HR>(水平線)を表現する方法各種(横の罫線、区切り線)

Last updated at Posted at 2017-07-15

Horizontal Line にひかれて

HTMLでいう**<HR>タグのように、横線/区切り線をシェルスクリプトで表現する各種方法**です。

fix / dynamic

罫線を引くには「固定長」と「可変長」の大きく2通りの方法があります。

  1. 固定長:「幅(線の長さ)を指定する」タイプ
  2. 可変長:「画面幅を取得して、そのぶんを繰り返す」タイプ

注意点

タイプ②のターミナルの横幅いっぱいの水平線を引くには tput コマンドが使える必要があります。

シェルが bashzsh などの環境なら大抵は大丈夫ですが、 sh (ボーンシェル)などがメインの tput コマンドがない環境や、ターミナル情報(環境変数の $TREM の値)が空の場合、情報が取得できずエラーが出ます。

特に、Docker などのコンテナのベース OS によっては tput コマンドも $TERM 変数はセットされていても cols コマンドが使えない場合はエラーが発生します。

tput: No value for $TERM and no -T specified

その場合に備えて、if などによる分岐が必要になります。

以下は、sh, bash, zsh のシェルで使えるサンプルです。ターミナルの横幅が取得できる場合は画面いっぱいに、取得できない場合は 80 文字の罫線を引きます。

罫線を引くサンプル
# Set width
$(tput cols 2>/dev/null 1>/dev/null) && {
    SCREEN_WIDTH=$(tput cols);
}
# If not supported fallback to default as 80 chars/line
SCREEN_WIDTH=${SCREEN_WIDTH:-80};

# Function to draw horizontal line
echo_hr(){
  printf -v _hr "%*s" ${SCREEN_WIDTH} && echo ${_hr// /${1--}}
}

# Usage
echo_hr

タイプ②の場合、基本的にどれも tput cols でターミナルの横幅を取得して画面横幅いっぱいに描画するのですが、結果は同じでもその過程で表現が違うのが面白いです。

固定長(指定した長さ)の水平線

もっとも単純な方法

echo --------------------
printf '%s\n' --------------------

繰り返し処理で表現する方法

forループで表現する

for ((x = 0; x < 20; x++)); do
  printf %s -
done
echo

yesコマンドで表現する

yes = | head --lines=20 | tr --delete '\n' ; echo

スペースをハイフンに置換して表現する

printf '%20s\n' | tr ' ' -
printf -v res %20s
printf '%s\n' "${res// /-}"

printf 関数を使って表現する

printf '%.0s-' {1..20}; echo

可変長(ターミナル画面いっぱい)の水平線

  • tput cols

文字の置換を使った表現方法

printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -

パラメーター指定の表現方法

hr="[WARNING]-[WARNING]-[WARNING]-[WARNING]-[WARNING]-[WARNING]-[WARNING]-[WARNING]-[WARNING]-[WARNING]-[WARNING]-"
printf '%s\n' "${hr:0:${COLUMNS:-$(tput cols)}}"

関数を使ってハイフンでなく直線で水平線を引く方法

hr() {
  local start=$'\e(0' end=$'\e(B' line='qqqqqqqqqqqqqqqq'
  local cols=${COLUMNS:-$(tput cols)}
  while ((${#line} < cols)); do line+="$line"; done
  printf '%s%s%s\n' "$start" "${line:0:cols}" "$end"
}

hr

関数を使って引数で渡された文字で水平線を引く方法

rule () {
  printf -v _hr "%*s" $(tput cols) && echo ${_hr// /${1--}}
}

# イコールを横幅いっぱいに引く
rule =

# 骸骨の文字絵を横幅いっぱいに引く
rule `echo -e "\\xE2\\x98\\xA0"`

printf 関数を使った表現方法

eval printf %.0s- '{1..'"${COLUMNS:-$(tput cols)}"\}; echo
eval printf %.1s '-{1..'"${COLUMNS:-$(tput cols)}"\}; echo
_=- command eval printf %s '"${_[0]"{0..'"${COLUMNS:-$(tput cols)}"'}"}"'; echo

#参考文献

5
5
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5