ターミナルに赤く印刷されるようにしようとしていますstderr
。以下のスクリプトは、デバッグ トラップ時に2
カスタムにリダイレクトします。8
exec 9>&2
exec 8> >(
while IFS='' read -r line || [ -n "$line" ]; do
echo -e "${RED}${line}${COLORRESET}"
done
)
function undirect(){ exec 2>&9; } # reset to original 9 (==2)
function redirect(){ exec 2>&8; } # set to custom 8
trap "redirect;" DEBUG
PROMPT_COMMAND='undirect;'
それはここ、わかりやすい説明付き。
非常にうまく動作しているようですが、改行で終了しない入力はまったく印刷されません。著者の言葉を引用しますゴスペスまた:
bash> echo -en "hi\n" 1>&2
hi <-- this is red
bash> echo -en "hi" 1>&2
bash> echo -en "hi" 1>&2
bash> echo -en "hi\n" 1>&2
hihihi <-- this is red
理由がわかりません。改行以外のコンテンツは、何らかのバッファに収まるようです。ファイル記述子に到達しないか8
、すぐには印刷されません。どこに行くのでしょうか? はredirect
毎回適切に呼び出されます。また、は区切り文字がないことを意味するので、行単位IFS=''
でエコーアウトされる理由がよくわかりません。8
バグ修正をいただければ幸いです。この質問に引用した回答をリンクしました。
この解決策全体は、Gilles が指摘したように、完璧ではありません。読み取り、stdin、プログレスバーに問題があり、どちらもできませんsu
。source
また、パイプの破損や予期しないターミナルの終了などの重大な問題が頻繁に発生します。私のリンクからここにたどり着いた方は、ぜひ使用を検討してください。https://github.com/sickill/stderred より代わりに、はるかに良くなりました(まだ問題はありません)(ただし、echo bla >&2
赤くなく、それぞれの問題は解決済みです)
答え1
改行が印刷された時点で、同じ行の一部として部分的な行の出力が得られました。行の部分はread
、内にバッファリングされます。それがその機能です:
の読むユーティリティは標準入力から1つの論理行を読み込む
たとえば、これは<foobar>
ではなく 1 秒後に印刷されます<foo><bar>
。
(echo -n foo ; sleep 1 ; echo bar) | (read x ; echo "<$x>")
入力を完全な行ではなく小さな部分でキャッチしたい場合は、Perl などを使用して別の方法を実行する必要があります。これは、<foo><bar\n>
(最後の の前に改行を付けて)を出力します。>
とは異なり、read
Perl は最後の改行を特別に処理しないためです。色付けでは問題にならないはずです。)
(echo -n foo ; sleep 1 ; echo bar) |
perl -e '$|=1; while(sysread STDIN,$a,9999) { print "<$a>"}'
環境で色の制御コード (RED
および) がエクスポートされている場合は、次のように Perl スクリプトからそれらを使用できます。COLORRESET
perl -e '$|=1; while(sysread STDIN,$a,9999) {print "$ENV{RED}$a$ENV{COLORRESET}"}'
答え2
Bash では、組み込み-d
のオプションを使用してread
、行末記号を定義できます。man bash
これは、次のように述べています。
-d delim The first character of delim is used to terminate the input line,
rather than newline.
定義されていない場合は、文字列を 1 行として扱い、出現をread
待ちます。ただし、オプションを使用する場合は、区切り文字として設定できます。もちろん、その場合は入力を NUL で終了する必要もあります。\n
-d
NUL
例:
printf "%s\0" $'x\n' y z | while IFS='' read -r -d $'\0' line
do
printf "%s\n" "$line"
done
出力:
x
y
z
もう一度言いますが、今度はループprintf
内のwhile
は と一致しません\n
。
printf "%s\0" $'x\n' y z | while IFS='' read -r -d $'\0' line
do
printf "%s" "$line"
done
出力:
x
yz(...)
を追加しました。(...)
これは、2 行目の最後に End-Of-Line がないことを意味します。ただし、テキストは引き続き処理され、印刷されます。