シェル関数は最初の引数を中央に置きます。

シェル関数は最初の引数を中央に置きます。

ナノテキストエディタでは、選択内容をコマンドとして送信でき、しばしばテキストを中央に配置する必要があるため、次のコードを考えました。

center() {
  str=$1
  # Strip leading and trailing whitespace from the string
  str=$(echo "$str" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
  str_len=${#str}
  margin=$(((80 - str_len) / 2))
  printf "%*s%s%*s\n" $margin "" "$str" $margin ""
}

しかし、私はスクリプトについてよく知らないので、このコードを改善する方法を知りたいです。

Bashソリューションに接続するのはなぜですか?私はこのシェルを使用しません。ただshで実行したいです。

答え1

シェルを使用していると仮定するとbash(そうでない場合はこの回答の最後を参照)、bash標準変数の拡張および拡張ワイルドカードパターン(1つ以上の空白に似た文字と一致する)を使用して、文字列からサイドスペースをより効率的に削除できます。str+([[:space:]])

shopt -s extglob

str=$1
str=${str##+([[:space:]])}  # strip at start
str=${str%%+([[:space:]])}  # strip at end

(で与えられた列に右揃えで印刷したい。勝つ+S)/2勝つは端子の幅です(出力によってはtput cols、しかし使用することもできます$COLUMNS)。S文字列の長さです(${#str})。

printf '%*s\n' "$(( ( $(tput cols) + ${#str} ) / 2 ))" "$str"

機能:

center () (
    shopt -s extglob

    str=$1
    str=${str##+([[:space:]])}
    str=${str%%+([[:space:]])}

    printf '%*s\n' "$(( ( $(tput cols) + ${#str} ) / 2 ))" "$str"
)

関数の本体はサブシェルです。これにより、extglobシェルオプションの設定は呼び出しシェルにあふれません。

依存関係なしextglob(すべてに適用sh):

center () {
    str=$(printf '%s\n' "$1" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
    printf '%*s\n' "$(( ( $(tput cols) + ${#str} ) / 2 ))" "$str"
}

静的80列幅でフォーマットするには、$(tput cols)に置き換えます。80

答え2

間に複数のスペースが連結されていない場合は、次のコマンドを使用してトリミングを簡素化できます。str=$(echo $1)

center () {
  str=$(echo $1)
  len=${#str}
  margin=$((($COLUMNS - len) / 2))
  printf "%${margin}s%s\n" " " "$str"
}

後にスペースを追加する必要はありません$str

関連情報