stdin/pipe でサブ/テキストを中央に配置する Bash スクリプト

stdin/pipe でサブ/テキストを中央に配置する Bash スクリプト

私はコンソールに集中した富を表示するためにPython3の小さなスクリプトを使用しています。純粋なbashでこれを行う方法を提案できますか?

ファイル:center.python3

#!/usr/bin/env python3

import sys, os

linelist = list(sys.stdin)

# gets the biggest line
biggest_line_size = 0
for line in linelist:
    line_lenght = len(line.expandtabs())
    if line_lenght > biggest_line_size:
        biggest_line_size = line_lenght

columns = int(os.popen('tput cols', 'r').read())
offset = biggest_line_size / 2
perfect_center = columns / 2
padsize =  int(perfect_center - offset)
spacing = ' ' * padsize # space char

text = str()
for line in linelist:
    text += (spacing + line)

divider = spacing + ('─' * int(biggest_line_size)) # unicode 0x2500
text += divider

print(text, end="\n"*2)

それから.bashrc

実行可能にした後chmod +x ~/center.python3:

fortune | ~/center.python3

編集する:後で私の意見に基づいてこのOPに返信しますが、今はもう少し読みやすくしています。

編集2: タブ拡張に関して @janos が指摘したバグを修正するために Python スクリプトを更新しました。

ここに画像の説明を入力してください。

ベストアンサー1

PythonからBashに1つずつ変換してみましょう。

Python:

#!/usr/bin/env python3

import sys, os

linelist = list(sys.stdin)

大きな打撃:

#!/usr/bin/env bash

linelist=()
while IFS= read -r line; do
    linelist+=("$line")
done

Python:

# gets the biggest line
biggest_line_size = 0
for line in linelist:
    line_lenght = len(line)
    if line_lenght > biggest_line_size:
        biggest_line_size = line_lenght

大きな打撃:

biggest_line_size=0
for line in "${linelist[@]}"; do
    # caveat alert: the length of a tab character is 1
    line_length=${#line}
    if ((line_length > biggest_line_size)); then
        biggest_line_size=$line_length
    fi
done

Python:

columns = int(os.popen('tput cols', 'r').read())
offset = biggest_line_size / 2
perfect_center = columns / 2
padsize =  int(perfect_center - offset)
spacing = ' ' * padsize # space char

大きな打撃:

columns=$(tput cols)
# caveat alert: division truncates to integer value in Bash
((offset = biggest_line_size / 2))
((perfect_center = columns / 2))
((padsize = perfect_center - offset))
if ((padsize > 0)); then
    spacing=$(printf "%*s" $padsize "")
else
    spacing=
fi

Python:

text = str()
for line in linelist:
    text += (spacing + line)

divider = spacing + ('─' * int(biggest_line_size)) # unicode 0x2500
text += divider

print(text, end="\n"*2)

大きな打撃:

for line in "${linelist[@]}"; do
    echo "$spacing$line"
done

printf $spacing 
for ((i = 0; i < biggest_line_size; i++)); do
    printf -- -
done
echo

より簡単なコピー - 貼り付けのための完全なスクリプト:

#!/usr/bin/env bash

linelist=()
while IFS= read -r line; do
    linelist+=("$line")
done

biggest_line_size=0
for line in "${linelist[@]}"; do
    line_length=${#line}
    if ((line_length > biggest_line_size)); then
        biggest_line_size=$line_length
    fi
done

columns=$(tput cols)
((offset = biggest_line_size / 2))
((perfect_center = columns / 2))
((padsize = perfect_center - offset))
spacing=$(printf "%*s" $padsize "")

for line in "${linelist[@]}"; do
    echo "$spacing$line"
done

printf "$spacing"
for ((i = 0; i < biggest_line_size; i++)); do
    printf ─  # unicode 0x2500
done
echo

考慮事項の概要

Bashの分割が切り捨てられます。したがってoffsetperfect_center、 の値がpadsize少しずつ異なる場合があります。

元のPythonコードにはいくつかの問題があります。

  1. タブ文字の長さは1です。これにより、次のように、区切り線が最も長い線より短くなることがあります。

                      Q:    Why did the tachyon cross the road?
                      A:    Because it was on the other side.
                      ──────────────────────────────────────
    
  2. 一部の行が区切り文字の長さより長い場合は、長さの代わりに最長の行をcolumns使用する方が良い場合があります。columns

おすすめ記事