GNU/Linux >> Linux の 問題 >  >> Linux

Stdin /pipeからFortune/textを中央に配置するための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スクリプトを更新します。

承認された回答:

これが私のスクリプトcenter.shです :

#!/bin/bash

readarray message < <(expand)

width="${1:-$(tput cols)}"

margin=$(awk -v "width=$width" '
    { max_len = length > width ? width : length > max_len ? length : max_len }
    END { printf "%" int((width - max_len + 1) / 2) "s", "" }
' <<< "${message[@]}")

printf "%s" "${message[@]/#/$margin}"

仕組み:

  • 最初のコマンドは、stdinの各行を配置します 配列内のmessage 表をスペースに変換した後(@NominalAnimalに感謝)
  • 2番目のコマンドは、パラメーター#1からウィンドウ幅を読み取り、それを変数widthに入れます。 。パラメータが指定されていない場合は、実際の端子幅が使用されます。
  • 3番目のコマンドはmessage全体を送信します awkへ 変数marginに配置されるスペースの文字列として左マージンを生成するため 。
    • 最初のawk行は、入力行ごとに実行されます。 max_lenを計算します 、最長の入力行の長さ(widthに制限されています )
    • 2番目のawk行は、すべての入力行が処理されたときに実行されます。 (width - max_len) / 2の文字列を出力します 空白文字
  • 最後のコマンドは、messageのすべての行を出力します marginを前に付けた後 彼らに

テスト:

$ fortune | cowthink | center.sh
                    _______________________________________
                   ( English literature's performing flea. )
                   (                                       )
                   ( -- Sean O'Casey on P. G. Wodehouse    )
                    ---------------------------------------
                           o   ^__^
                            o  (oo)\_______
                               (__)\       )\/\
                                   ||----w |
                                   ||     ||

$ echo $'|\tTAB\t|' | center.sh 20
  |       TAB     |

$ echo "A line exceeding the maximum width" | center.sh 10
A line exceeding the maximum width

最後に、Pythonスクリプトのように区切り線で表示を終了する場合は、最後のprintfの前にこの行を追加します。 コマンド:

message+=( $(IFS=''; sed s/./─/g <<< "${message[*]}" | sort | tail -n1)$'\n' )

すべての行のすべての文字をに置き換えます。 、sort | tail -n1 、メッセージの最後に追加します。

関連:ReadyNAS Duo v1でファイルをアルファベット順のフォルダに並べ替えるBashスクリプト?

テスト:

$ fortune | center.sh  60
     Tuesday is the Wednesday of the rest of your life.
     ──────────────────────────────────────────────────

Linux
  1. コマンドライン引数をBashスクリプトに渡しますか?

  2. Bashスクリプトでクリップボードとの間でパイプする

  3. コマンドLinuxラインからのmatlab実行スクリプト

  1. bashスクリプトが同時に実行されないようにする

  2. bash の改行でテキストをエコーする

  3. Bash履歴ファイルから特定の行を削除します

  1. フォルダから最も古いファイルを削除するためのBashスクリプト?

  2. Bashスクリプト:ファイルがテキストファイルかどうかを確認しますか?

  3. 着信メールをText/plainからText/htmlに変更しますか?