Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
3
Help us understand the problem. What is going on with this article?
@KEINOS

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

More than 1 year has passed since last update.

Horizontal Line にひかれて

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

fix / dynamic

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

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

注意点

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

シェルが bash なら大抵大丈夫ですが、 sh (ボーンシェル)などの tput コマンドがない環境、ターミナル情報(環境変数の $TREM の値が空)の場合、Docker などのコンテナによっては 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);
}
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

参考文献

3
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
KEINOS
A Japanese made in Mexico with Mexican quality ;-) Who monkey around the jungle of codes. 記事の日本語がおかしかったら遠慮なく編集リクください。また、記事に「LGTM」が付くたび、やる気に比例して見直して何かしら加筆・修正してブラッシュアップしています。基本的に変更通知はお送りしません。
qiitadon
Qiitadon(β)から生まれた Qiita ユーザー・コミュニティです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
3
Help us understand the problem. What is going on with this article?