このスクリプトは5行を出力し、3行目に下線が引かれています。
#!/usr/bin/env bash
set -eu
bold=$(tput bold)
reset=$(tput sgr0)
underline=$(tput smul)
echo 'line 1
line 2
line 3
line 4
line 5' | awk -v bold="$bold" -v reset="$reset" -v underline="$underline" '
NR == 3 {print underline $0 reset}
NR != 3 {print $0}
'
3行目の終わりで(スクリプトで)リセットしないと、次に(シェルで)入力するコマンドを含め、次のすべての行に下線が引かれます。 reset
を実行するまで。 less
(./my-script.sh | less -R
)reset
(スクリプト内)は不要である(3行目に下線が引かれている)だけでなく、tmux
(^O
、TERM=screen-256color
):
line 1
line 2
line 3^O
line 4
line 5
しかし、プレーンコンソールには記号がありません(TERM=xterm-256color
)。
正確には何が、なぜそれが起こるのですか?これらすべての場合にスクリプトを機能させる方法はありますか?
$ ./my-script.sh
$ ./my-script.sh | grep line --color=never
$ ./my-script.sh | less -R
たとえば、 次のスクリプト をより適切に機能させるため。
less
は、行の終わりに独自の「リセット」を送信します。これは、terminfo sgr0
から(ncurses)によって^O
(代替文字セットをリセット)を削除することによって派生します。 less
はtermcapインターフェースを使用しています。 terminfosgr0に対応するtermcap機能meは、マニュアルページに記載されているように、通常、代替文字セットの状態を変更しません。 curs_termcap(3x) :
Termcapには、terminfoの
sgr
文字列に類似したものは何もないことに注意してください。この結果の1つは、termcapアプリケーションがme
(terminfosgr0
)代替文字セットはリセットされません。この実装は、この点でtermcapの制限に対応するために、termcapインターフェースに表示されるデータをチェックおよび変更します。
おそらく、less
は、予期しないエスケープシーケンスから回復するためにリセットを実行しています。-R
オプションは、ANSIカラー(および太字、下線、点滅、目立つなどの同様の形式のエスケープ)を処理するようにのみ設計されています。ソースコードはそれについて言及していませんが、A_NORMAL
割り当てはless
に後でリセットを発行するように指示します。
/*
* Add a newline if necessary,
* and append a '\0' to the end of the line.
* We output a newline if we're not at the right Edge of the screen,
* or if the terminal doesn't auto wrap,
* or if this is really the end of the line AND the terminal ignores
* a newline at the right Edge.
* (In the last case we don't want to output a newline if the terminal
* doesn't ignore it since that would produce an extra blank line.
* But we do want to output a newline if the terminal ignores it in case
* the next line is blank. In that case the single newline output for
* that blank line would be ignored!)
*/
if (column < sc_width || !auto_wrap || (endline && ignaw) || ctldisp == OPT_ON)
{
linebuf[curr] = '\n';
attr[curr] = AT_NORMAL;
curr++;
}
sgr0
の代わりに(allビデオをリセットします属性、そして一部しか理解されていない)、あなたはすることができます
reset=$(tput rmul)
および(TERM=screen-256color
を含む多くの端末/多くのシステムの場合)下線だけをリセットします。ただし、それはboldには影響せず、太字をリセットする従来のterminfo/termcap機能もありません。 。ただし、screenはこれを行う対応するECMA-48シーケンスを実装しているため(SGR22とrmul
で使用される24)、その場合はハードコーディングできます。