プロセスが実行中かどうかを表示するbashシェルスクリプトを書いています。
これまでのところ、私はこれを得ました:
printf "%-50s %s\n" $PROC_NAME [UP]
コードは私にこの出力を与えます:
JBoss [DOWN]
GlassFish [UP]
verylongprocessname [UP]
2つのフィールド間のギャップを「-」または「*」で埋めて読みやすくします。フィールドの配置を乱すことなくそれを行うにはどうすればよいですか?
私が欲しい出力は次のとおりです。
JBoss ------------------------------------------- [DOWN]
GlassFish --------------------------------------- [UP]
verylongprocessname ----------------------------- [UP]
Pure Bash、外部ユーティリティなし
このデモンストレーションでは完全な正当化が行われますが、不規則な右の行が必要な場合は、2番目の文字列の長さの減算を省略できます。
pad=$(printf '%0.1s' "-"{1..60})
padlength=40
string2='bbbbbbb'
for string1 in a aa aaaa aaaaaaaa
do
printf '%s' "$string1"
printf '%*.*s' 0 $((padlength - ${#string1} - ${#string2} )) "$pad"
printf '%s\n' "$string2"
string2=${string2:1}
done
残念ながら、この手法では、パッドストリングの長さは、必要と思われる最長の長さよりも長くなるようにハードコード化する必要がありますが、示されているように、パッド長は変数にすることができます。ただし、パッドの長さの変数を使用できるように、最初の行を次の3行に置き換えることができます。
padlimit=60
pad=$(printf '%*s' "$padlimit")
pad=${pad// /-}
そのため、パッド(padlimit
およびpadlength
)は、端末の幅($COLUMNS
)に基づくか、最長のデータ文字列の長さから計算できます。
出力:
a--------------------------------bbbbbbb
aa--------------------------------bbbbbb
aaaa-------------------------------bbbbb
aaaaaaaa----------------------------bbbb
2番目の文字列の長さを差し引くことなく:
a---------------------------------------bbbbbbb
aa--------------------------------------bbbbbb
aaaa------------------------------------bbbbb
aaaaaaaa--------------------------------bbbb
最初の行は代わりに同等のものである可能性があります(sprintf
と同様):
printf -v pad '%0.1s' "-"{1..60}
またはより動的な手法の場合も同様です。
printf -v pad '%*s' "$padlimit"
必要に応じて、すべてを1行で印刷できます。
printf '%s%*.*s%s\n' "$string1" 0 $((padlength - ${#string1} - ${#string2} )) "$pad" "$string2"
ピュアバッシュ。 「PROC_NAME」の値の長さを固定文字列「line」のオフセットとして使用します。
line='----------------------------------------'
PROC_NAME='abc'
printf "%s %s [UP]\n" $PROC_NAME "${line:${#PROC_NAME}}"
PROC_NAME='abcdef'
printf "%s %s [UP]\n" $PROC_NAME "${line:${#PROC_NAME}}"
これは与える
abc ------------------------------------- [UP]
abcdef ---------------------------------- [UP]
これが最も簡単な解決策だと思います。 Pure Shellビルトイン、インライン演算なし。以前の回答から借用しています。
部分文字列と$ {#...}メタ変数のみ。
A="[>---------------------<]";
# Strip excess padding from the right
#
B="A very long header"; echo "${A:0:-${#B}} $B"
B="shrt hdr" ; echo "${A:0:-${#B}} $B"
生産する
[>----- A very long header
[>--------------- shrt hdr
# Strip excess padding from the left
#
B="A very long header"; echo "${A:${#B}} $B"
B="shrt hdr" ; echo "${A:${#B}} $B"
生産する
-----<] A very long header
---------------<] shrt hdr
簡単な(しかし機能する)ソリューション:
echo -e "---------------------------- [UP]\r$PROC_NAME "
printf
を使用してスペース以外を埋め込む方法はありません。 sed
を使用できます:
printf "%-50s@%s\n" $PROC_NAME [UP] | sed -e 's/ /-/g' -e 's/@/ /' -e 's/-/ /'
echo -n "$PROC_NAME $(printf '\055%.0s' {1..40})" | head -c 40 ; echo -n " [UP]"
説明:
printf '\055%.0s' {1..40}
-40個のダッシュを作成"$PROC_NAME ..."
-$ PROC_NAMEとダッシュを連結します| head -c 40
-文字列を最初の40文字にトリミングしますこれはさらに簡単で、外部コマンドを実行しません。
$ PROC_NAME="JBoss"
$ PROC_STATUS="UP"
$ printf "%-.20s [%s]\n" "${PROC_NAME}................................" "$PROC_STATUS"
JBoss............... [UP]
echo
のみを使用
@Dennis Williamsonのanwserは、エコーを使用してこれを実行しようとしていたことを除いて、正常に機能しています。 Echoでは、特定の色の文字を出力できます。 printfを使用すると、そのカラーリングが削除され、読み取り不能な文字が印刷されます。 echo
- onlyの代替案は次のとおりです。
string1=abc
string2=123456
echo -en "$string1 "
for ((i=0; i< (25 - ${#string1}); i++)){ echo -n "-"; }
echo -e " $string2"
出力:
abc ---------------------- 123456
もちろん、右部分を左揃えにするか右揃えにするかに関わらず、@ Dennis Williamsonが提案するすべてのバリエーションを使用できます(25 - ${#string1}
を25 - ${#string1} - ${#string2}
などに置き換えます)。
自動スケーリング/サイズ変更の方法と例による単純なコンソールスパン/フィル/パッド/パディング。
function create-console-spanner() {
# 1: left-side-text, 2: right-side-text
local spanner="";
eval printf -v spanner \'"%0.1s"\' "-"{1..$[$(tput cols)- 2 - ${#1} - ${#2}]}
printf "%s %s %s" "$1" "$spanner" "$2";
}
例:create-console-spanner "loading graphics module" "[success]"
現在は、フル機能のカラー文字端末スイートで、色の印刷に関するすべてのことを行い、スパナ付きの書式設定された文字列。
# Author: Triston J. Taylor <[email protected]>
# Date: Friday, October 19th, 2018
# License: OPEN-SOURCE/ANY (NO-PRODUCT-LIABILITY OR WARRANTIES)
# Title: Paint.sh
# Description: color character terminal driver/controller/suite
declare -A Paint=([none]=`tput sgr0` [bold]=`tput bold` [black]=`tput setaf 0` [red]=`tput setaf 1` [green]=`tput setaf 2` [yellow]=`tput setaf 3` [blue]=`tput setaf 4` [Magenta]=`tput setaf 5` [cyan]=`tput setaf 6` [white]=`tput setaf 7`);
declare -i Paint_ACTIVE=1;
function Paint-replace() {
local contents=$(cat)
echo "${contents//$1/$2}"
}
source <(cat <<EOF
function Paint-activate() {
echo "\$@" | $(for k in ${!Paint[@]}; do echo -n Paint-replace \"\&$k\;\" \"\${Paint[$k]}\" \|; done) cat;
}
EOF
)
source <(cat <<EOF
function Paint-deactivate(){
echo "\$@" | $(for k in ${!Paint[@]}; do echo -n Paint-replace \"\&$k\;\" \"\" \|; done) cat;
}
EOF
)
function Paint-get-spanner() {
(( $# == 0 )) && set -- - 0;
declare -i l=$(( `tput cols` - ${2}))
eval printf \'"%0.1s"\' "${1:0:1}"{1..$l}
}
function Paint-span() {
local left_format=$1 right_format=$3
local left_length=$(Paint-format -l "$left_format") right_length=$(Paint-format -l "$right_format")
Paint-format "$left_format";
Paint-get-spanner "$2" $(( left_length + right_length));
Paint-format "$right_format";
}
function Paint-format() {
local VAR="" OPTIONS='';
local -i MODE=0 PRINT_FILE=0 PRINT_VAR=1 PRINT_SIZE=2;
while [[ "${1:0:2}" =~ ^-[vl]$ ]]; do
if [[ "$1" == "-v" ]]; then OPTIONS=" -v $2"; MODE=$PRINT_VAR; shift 2; continue; fi;
if [[ "$1" == "-l" ]]; then OPTIONS=" -v VAR"; MODE=$PRINT_SIZE; shift 1; continue; fi;
done;
OPTIONS+=" --"
local format="$1"; shift;
if (( MODE != PRINT_SIZE && Paint_ACTIVE )); then
format=$(Paint-activate "$format&none;")
else
format=$(Paint-deactivate "$format")
fi
printf $OPTIONS "${format}" "$@";
(( MODE == PRINT_SIZE )) && printf "%i\n" "${#VAR}" || true;
}
function Paint-show-pallette() {
local -i Paint_ACTIVE=1
Paint-format "Normal: &red;red &green;green &blue;blue &Magenta;magenta &yellow;yellow &cyan;cyan &white;white &black;black\n";
Paint-format " Bold: &bold;&red;red &green;green &blue;blue &Magenta;magenta &yellow;yellow &cyan;cyan &white;white &black;black\n";
}
色を印刷する、それは十分に簡単です:Paint-format "&red;This is %s\n" red
そして、後で太字にしたいかもしれません:Paint-format "&bold;%s!\n" WOW
-l
関数のPaint-format
オプションはテキストを測定するため、コンソールフォントメトリックス操作を実行できます。
-v
関数のPaint-format
オプションはprintf
と同じように機能しますが、-l
で提供することはできません
スパニングの現在!
Paint-span "hello " . " &blue;world"
[注:改行のターミナルシーケンスは追加しませんでしたが、テキストはターミナルを埋めるため、次の行は改行のターミナルシーケンスにしか見えません]
そして、その出力は次のとおりです。
hello ............................. world
ここに別のものがあります:
$ { echo JBoss DOWN; echo GlassFish UP; } | while read PROC STATUS; do echo -n "$PROC "; printf "%$((48-${#PROC}))s " | tr ' ' -; echo " [$STATUS]"; done
JBoss -------------------------------------------- [DOWN]
GlassFish ---------------------------------------- [UP]
いくつかの固定列番号で埋め込み文字を終了する場合は、cut
をオーバーパッドして長さを調整できます。
# Previously defined:
# PROC_NAME
# PROC_STATUS
PAD="--------------------------------------------------"
LINE=$(printf "%s %s" "$PROC_NAME" "$PAD" | cut -c 1-${#PAD})
printf "%s %s\n" "$LINE" "$PROC_STATUS"
シンプルですが、動作します:
printf "%-50s%s\n" "$PROC_NAME~" "~[$STATUS]" | tr ' ~' '- '
使用例:
while read PROC_NAME STATUS; do
printf "%-50s%s\n" "$PROC_NAME~" "~[$STATUS]" | tr ' ~' '- '
done << EOT
JBoss DOWN
GlassFish UP
VeryLongProcessName UP
EOT
Stdoutへの出力:
JBoss -------------------------------------------- [DOWN]
GlassFish ---------------------------------------- [UP]
VeryLongProcessName ------------------------------ [UP]
Bash + seqでパラメーター展開が可能
@Dennis Williamsonの回答に似ていますが、seq
が利用可能な場合、パッド文字列の長さをハードコーディングする必要はありません。次のコードにより、変数を定位置パラメーターとしてスクリプトに渡すことができます。
COLUMNS="${COLUMNS:=80}"
padlength="${1:-$COLUMNS}"
pad=$(printf '\x2D%.0s' $(seq "$padlength") )
string2='bbbbbbb'
for string1 in a aa aaaa aaaaaaaa
do
printf '%s' "$string1"
printf '%*.*s' 0 $(("$padlength" - "${#string1}" - "${#string2}" )) "$pad"
printf '%s\n' "$string2"
string2=${string2:1}
done
シェルがコマンドフラグとして解釈しないように、文字「-」の代わりにASCIIコード「2D」が使用されます。別のオプションは、「=」を使用する「3D」です。
引数としてパディング長が渡されない場合、上記のコードはデフォルトで80文字の標準端末幅になります。
Bashシェル変数COLUMNS
(つまり、現在の端末の幅)を利用するには、スクリプトで環境変数を使用できる必要があります。 1つの方法は、次のように、.
(「ドット」コマンド)が前に付いたスクリプトを実行することにより、すべての環境変数を取得することです。
. /path/to/script
または(より良い)次のように、実行時にCOLUMNS
変数を明示的に渡します。
/path/to/script $COLUMNS