printf "%*s\n" $(((${#fname}+$COLUMNS)/2)) "$fname"
次のエラーが発生します。
line 9: (7+)/2: syntax error: operand expected (error token is ")/2")
これは端末では機能しますが、私のスクリプトでは機能しません。どんな考えがありますか?
答え1
すべてのシェルが$COLUMNS
変数を端末幅に設定するわけではありません。
bash
5.0より前のバージョンでは、スクリプトではなくインタラクティブにのみ設定されていました。ただし、バージョン4.3以降は、非対話型シェルで引き続き使用できますshopt -s checkwinsize
。
しかし、どちらの場合も反転があります。非対話型シェルでオプションを有効にすると(5.0以降はデフォルトで有効になっています)、$COLUMNS
子プロセスが待って終了するまで/は設定されません(ソースに記載されている項目)。$LINES
NEWS
フォアグラウンドジョブが終了した後、非対話型シェルには基本的に作業制御がないため、多少誤解を招くおそれがあります。したがって、これらの変数を使用する前に、外部コマンドまたはサブシェルが同期的に実行されることを確認する必要があります。
#! /bin/bash -
shopt -s checkwinsize # for versions 4.3 and 4.4
(:) # start a synchronous subshell that runs the null command
echo "$COLUMNS $LINE"
また、これはstderrが端末に移動したときにのみ発生するため(そうでない場合は設定されていないまま)、画面の幅を決定できない場合は$COLUMNS
より合理的なデフォルトを使用することをお勧めします。${COLUMNS:-80}
bash
または、端末で実行している場合は非対話型であってもzsh
常に設定を切り替えるか(それ以外の場合はデフォルト値は80)、Bourneに似たシェルでif出力を使用して以前に設定した場合に設定できます。設定されていないか空です。$COLUMNS
$COLUMNS
${COLUMNS:=$(tput cols)}
$COLUMNS
$COLUMNS
tput cols
tput cols
システムで機能しない場合は試してみてください。</dev/tty stty size | awk '{print $2}'
またはzsh -c 'print $COLUMNS'
ただし、この方法で設定すると端末のサイズが変更されるたびに更新されないため、スクリプトから中央揃えのテキストを印刷するたびに端末のサイズが照会されるように常に代わりに$COLUMNS
使用することをお勧めします。$(tput cols)
また参考にしてくださいprintf '%*s'
zsh
シェルの外からfish
与えられた量だけテキストを埋め、バイトいいえ数値したがって、この方法は、UTF-8を使用するロケールでUS-ASCII文字(すべての可能な文字の0.011%)に制限された単一バイト、単一幅文字を含むテキストを埋めるためにのみ使用できます。
zsh
代わりにを使用している場合は、eftパラメータとightパディングパラメータを使用してbash
拡張フラグを使用できます(このフラグを使用して、幅が0または幅が2つの文字を処理することもできます)。l
r
m
print -r -- ${(ml[COLUMNS/2]r[COLUMNS-COLUMNS/2])fname}
左右(つまり画面の右端)を埋めることに注意してください。以下を使用して、右側のパディング(および末尾のスペース)を削除できます。
set -o extendedglob
print -r -- ${${(ml[COLUMNS/2]r[COLUMNS-COLUMNS/2])fname}%%[[:space:]]#}
色付け/太字/強調表示...エスケープシーケンスを含む中央テキストはより複雑です。最も簡単な方法は、おそらく文字列の幅を取得する前に削除することです。例えばzsh
その方法文字列の幅を決定し、幅が0または幅が2つの文字を処理します。
varwidth() (( ${(P)#1} * 3 - ${#${(ml[${(P)#1} * 2])${(P)1}}} ))
functions -Ms varwidth
varwidth_without_formatting() {
set -o localoptions -o extendedglob
local without_formatting=${(P)1//$'\e'\[[0-9;]#m}
(( varwidth(without_formatting) ))
}
functions -Ms varwidth_without_formatting
center() {
local text
for text do
print -r -- ${(l[(COLUMNS-varwidth_without_formatting(text))/2])}$text
done
}
center $'\e[31mred\e[1;39mbold\e[m' \
${(%):-%F{green}Blah%F{yellow}blah%F{magenta}blah%f}
1ほとんどのシステムでは、@zevzekがコメントに示すようにSIGWINCHシグナル用のハンドラをインストールできますが、これは最も一般的な場合に役立ちます。
答え2
COLUMNS変数の代わりに外部ソースから値を取得できます。
tput cols
stty size | cut '-d ' -f1
答え3
以下を試してください。
read WindowHeight WindowWidth<<<$(stty size)
printf "%$(((${#fname}+${WindowWidth})/2))s" "$fname"
COLUMNSはスクリプトで自動的に設定されないため、最良のオプションはsttyを使用して現在のウィンドウサイズを取得することです。これは複数のシェル(bash、ksh、zshを含む)で機能します。