ANSIエスケープコードを使用した文字列のソート

ANSIエスケープコードを使用した文字列のソート

設定されたオプションの色が緑色で、設定されていないオプションの色が赤色のすべてのzshオプションのソートされたリストを印刷しようとしています。ただし、sortカラーラインでは機能しません。次はすべての赤いオプションを印刷し、すべての緑色のオプションを印刷します。

print -lP "%F{green}"${^$(setopt)} "%F{red}"${^$(unsetopt)} | sort

各オプション行が赤と緑print -Pで始まるようにフォーマット文字列が拡張されたためです。見ている^[[31m^[[32msortマンページ、助けることができる2つのオプションがあります。

-i, --ignore-nonprinting 印刷可能文字のみを考慮する

-k, --key=POS1[,POS2] POS1 (開始点 1) でキーを開始し、POS2 (基本行末) で終了します。

だから私は次のことを試みます:

print -lP "%F{green}"${^$(setopt)} "%F{red}"${^$(unsetopt)} | sort -i

そして

print -lP "%F{green}"${^$(setopt)} "%F{red}"${^$(unsetopt)} | sort --key=<N>

<N>さまざまな数字を設定してみました。すべての場合で同じ結果が得られます(すべての赤いオプションが緑の前に来ます)。この問題をどのように解決できますか?

答え1

-kソートオプションは、フィールドと文字という2つの数値引数を使用します。最初のフィールドの6番目の文字に基づいてソートしようとしています。%F{green}交換されてから6番目の文字ですESC[32m。だからこれはうまくいきます:

print -lP "%F{green}"${^$(setopt)} "%F{red}"${^$(unsetopt)} | sort -k 1.6

答え2

などのエスケープシーケンスでは、^[[31mエスケープ文字^[は印刷できない文字ですが、他の文字[31mは印刷文字です。したがって、sort -i役に立ちません。エスケープ文字は無視されますが、まだ[31mred[0m以前に並べ替えられます[32mgreen[0m

ユーティリティに組み込まれている機能以上の基準に従ってデータをソートする一般的な方法sortは、各行のデータを倍増し、最初のコピーがソートキーになるように処理し、行をソートして最後に最初の部分を削除することです。たとえば、ソートするデータにタブ文字が含まれていないとします。

awk '{s=$0; gsub(/\033\[[ -?]*[@-~]/,"",s); print s "\t" $0}' |
sort |
awk 'BEGIN {RS="\t"} {print $2}'

関連情報