Horizontal Line にひかれて
HTMLでいう**<HR>
タグのように、横線/区切り線をシェルスクリプトで表現する各種方法**です。
fix / dynamic
罫線を引くには「固定長」と「可変長」の大きく2通りの方法があります。
- 固定長:「幅(線の長さ)を指定する」タイプ
- 可変長:「画面幅を取得して、そのぶんを繰り返す」タイプ
注意点
タイプ②のターミナルの横幅いっぱいの水平線を引くには tput
コマンドが使える必要があります。
シェルが bash
や zsh
などの環境なら大抵は大丈夫ですが、 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
#参考文献
- The printf command @ Bash Hackers
http://wiki.bash-hackers.org/commands/builtin/printf - Print ahorizontal line @ Bash Hackers
http://wiki.bash-hackers.org/snipplets/print_horizontal_line - Shell trick:Printf rules @ brettterpstra.com
http://brettterpstra.com/2015/02/20/shell-trick-printf-rules/ - Bash/プロンプトのカスタマイズ |
ArchWiki @ arch linux
https://wiki.archlinuxjp.org/index.php/Bash/%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA - @nakataSyunsuke さんのコメント