bash関数に渡された複数の文字列引数があり、各引数は別々の行に印刷されます。
warn
最初のパラメータから赤で印刷された行数だけ値が表示されるようにコードを変更したいと思います${@}
。
rge='^[0-9]+$'
if [[ -v warn && "$warn" == "1" ]]; then
printf '%s\n' ${red}"$1"${sgr} # first line red
printf '%s\n' "${@:2}" # remaining, uncoloured
elif [[ -v warn && "$warn" =~ $rge ]]; then
printf '%s\n' ${red}"$@"${sgr} # all lines red
fi
最初の試みで
elif [[ -v warn && "$warn" =~ $rge ]]; then
argc=$#
argv=("$@")
printf "%s\n" "argc: $argc"
for (( j=0; j<warn; j++ )); do
printf '%s\n' ${red}"${argv[j]}"${sgr}
done
#printf '%s\n' ${red}"$@"${sgr} # all lines red
fi
ベストアンサー1
入力行番号など、さまざまな条件に基づいてさまざまなタスクを実行する方法を既に知っている既存のツールを活用してください。たとえば、awk、sed、Perl、Pythonなどがあります。
ところでshでもできますが、なぜそうでしょうか?シェルループは、ほぼ常にあらゆる形式のテキスト処理を実行する最悪の方法です。
たとえば、以下では、シェルを使用して環境変数を設定し、次に色を強調表示しますawk
(a)シェルの行数を計算し、b)読み取りループ中にシェルを使用して素早く、厄介な、簡単で簡単な操作を実行する防止しますawk
。
colourise() {
# colourise all (default) or the first N lines of stdin
# where N is the optional first argument to the function.
# check if arg is empty or numeric
[ -z "$1" ] || [[ "$1" =~ ^[0-9]+$ ]] \
|| echo "optional arg must be numeric if supplied" && exit 1
local colour="$(tput setaf 9)"
local sgr0="$(tput sgr0)"
awk -v c="$colour" -v s="$sgr0" -v w="$1" \
'(NR <= w || w == "") {print c $0 s; next}1'
}
ところで、awkスクリプトから直接カラーコードとsgrコードをハードコードできます。その後、 "$1" の値を awk に渡します (またはexport warn="$1"
シェルで awk で ENVIRON["warn"] を使用)。ただし、awkには機能がないため、tput
これを手動で実行する必要があります。たとえば、以下は、vt100、ansi、xtermなどのほとんどの端末で動作します。
colourise() {
local warn="$1"
export warn
awk 'BEGIN {c="\033[91m"; s="\033[m\017"; w=ENVIRON["warn"]}
(NR <= w || w == "") {print c $0 s; next}1'
}
または(ターミナルのハードコーディングエスケープシーケンスが悪いので):
colourise() {
local warn="$1"
local colour="$(tput setaf 9)"
local sgr0="$(tput sgr0)"
export warn colour sgr0
awk 'BEGIN {c=ENVIRON["colour"]; s=ENVIRON["sgr0"]; w=ENVIRON["warn"]}
(NR <= w || w == "") {print c $0 s; next}1'
}
次に、必要なものをcolourise
関数にパイプします。例えば
# colourise first three lines of an array
printf "%s\n" "${array[@]}" | colourise 3
# colourise all lines of head
head filename | colourise
# colourise only the first line of the output from several
# commands. use a compound command {} or a sub-shell ()
# this does not colourise the first line of each command separately,
# only the first line of the combined output.
{
command1
command2
command3
} | colourise 1