「列」の出力がANSIカラー入力と一致しないのはなぜですか?

「列」の出力がANSIカラー入力と一致しないのはなぜですか?

一部のデータを取得するためにコマンドラインを使用しています(カール)、関連フィールド抽出(アッ)形式を指定し()。

見苦しいですがうまくいきます(しかし、すべてのスクリプトは「長くて醜い」1行)しかし、特定の色をリストしようとすると間違っています。

これは単純な(単純化された)バージョンです。働く:

curl "http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc" 2>/dev/null  \
 | awk 'BEGIN { FS= "|"; OFS= "|" }  {print  $1, $2, $5, $10, $11, $13}' \
 | column -t -s '|'

今、いくつかのフィールドに下線を引いていくつかを追加したいと思います。ANSIエスケープコードまったく:

curl "http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc" 2>/dev/null  \
 | awk 'BEGIN { FS= "|" ; OFS= "|" }  \
     $13~/Rieti/||/Perugia/ {$13="\033[1;31m"$13"\033[0m"} \
     $11~/[0-9]+/ && $11 > 5.8 {$11="\033[1;33m"$11"\033[0m"} 
     {print  $1, $2, $5, $10, $11, $13 }' \
 | column -t -s '|'

ソートが正しくありません(図を参照)。

ここに画像の説明を入力してください。

なぜ?どうすれば解決できますか?

修正する

私はこの質問を見たことがあります列コマンドとカラーエスケープコードに関する問題しかし、彼の答えはフルカラーラインの場合に適用されるので、私の問題を解決することはできません。

私の場合、次の理由で回答を適用または調整することはできません(またはできません)。

  1. 問題は、後続の列に関係なく、$ 11の列が着色された場合に制限されます。
  2. カラーコードを追加する良い方法やエレガントな方法は見えません。後ろに柱。
    テストのために列の出力をawkに送信する場合は、フィールドを適切に分離するようにawkに指示する方法がわかりません(フィールドがより多くのスペースで区切られている場合は正規表現を使用できますが、場合によっては区切りが単一のスペースで、awkフィールドを区切ります。記号で単語間のスペースとスペースを認識する方法がわかりません。

私が見ることができる唯一のことは、リセットカラーコードを割り当てから印刷ブロックに移動することです。最初出力専用バージョンのように、行間隔がより良いです(下の\033[0m2番目のコマンドラインの下線を参照)。 ここに画像の説明を入力してください。

ではどうやって解決しますか?私のように着色するよりエレガントな方法がありますか?

(私は知っています。Perlラインを使用するとより良いことができますが、問題があると思います。)

答え1

この問題を解決するには3つの簡単な方法があります。

  1. 同じ長さを維持するには、常にこの列にエスケープシーケンスを使用してください。
  2. エスケープ文字を独自の列(追加の4列)に入れます。ただし、これにより、出力に余分なスペースが追加されます。
  3. column提案どおりにフォーマットしてください。

その他の注意事項はここにあります。ANSIエスケープコードを含む入力データを「表にする」ためのシェルツール

最初のオプションでは、\033[1;31mredだけを使用する代わりに\033[31;1mredを使用し、\033[31;0m前のコード、または同じシーケンスのコードも取り消す「赤ではない」、または通常のゼロコードを使用してください。これにより、すべての列のエスケープコードの長さが等しくなります。

BEGIN { FS=OFS="|" }  
function colour(ss,cc)    { return "\033[" cc ";1m" ss "\033[0m"; }
function notcolour(ss,cc) { return "\033[" cc ";0m" ss "\033[0m"; }
{  
  if ($13~/(RI|PG)/)    { $13=colour($13,31)    } 
                   else { $13=notcolour($13,31) }
  if (($11+0) > 5.8)    { $11=colour($11,33)    }
                   else { $11=notcolour($11,33) }
  print $1, $2, $5, $10, $11, $13 
}

(ソースデータの変更と一致するなど、いくつかのマイナーな簡略化と修正も上記に適用されました。)

このアプローチの問題は、column合計によって異なりますlibc。 (私はutil-linux-2.23.2から来ました。)印刷できないコンテンツが見つかった場合、column実際の幅ではなく戻りコードは-1になります。wcswidth()これは実際にテーブル形式を混乱させます。 util-linux-2.30.1 の最新バージョンは新しいバージョンを使用します。図書館問題を解決するが印刷できないコンテンツを16進符号化バージョンに置き換えてそれを行います。\xしたがって、元のエスケープが完全に失われます。 // エレガントでない方法で修正できます。

curl ... | awk ... | column -t -s '|' | while read -r line; do printf "$line\n"; done

printf脱出を説明する場所。同じ効果を得る\033には、独自のコードに置き換えることができます。\\x1bLinuxを使用しているかどうかはわかりません。 )

3番目のオプションでは、出力区切り記号の設定をcolumnサポートする必要があり、デフォルトは2つのスペースです。-o""に設定すると、|次のことができます。

curl ... | column -t -s "|" -o "|" | awk '
BEGIN { FS="|" }  
function colour(ss,cc) { return sprintf("\033[%i;1m%s\033[0m",cc,ss) }
{  
  if ($13~/(RI|PG)/) { $13=colour($13,31) } 
  if (($11+0) > 5.8) { $11=colour($11,33) }
  print $1, $2, $5, $10, $11, $13 
}'

ここでの秘密は、columnパイプで区切られた入力を使用することです。そして出力すると、幅が固定され、awkすべての重要なスペースを保存しながらを使用して安全に処理できます。columnサポートしていない場合は、-o以下を使用して偽にすることができます。

curl ... | sed -e 's/|/^|/g' | column -t -s^ | awk ...

これは区切り文字を " ^|"に倍増し、をcolumn使用し^、awkusesを使用します|。これにより、仮説が^データに確実に存在しなくなります。ハードタブが機能する可能性があります。

今「理由」を知っていると思います。しかし、明確に申し上げれば、次のようになります。

  • columnstrlen()wcslen()/が端末に表示されている長さと一致しないオクテット(または文字)を素早く計算できます
  • column長さを計算するために使用することisprint()ができ、端末エスケープにも正しくありません。
  • column印刷できないコンテンツが見つかると、すべての列が削除される可能性があります(私の場合と同じように)。

カラーコードシーケンスを削除することはかなり簡単な問題ですが、column

答え2

このコードはOPで修正されました。

# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }

pl " Results, highlight:"
# Original code from post:
# curl "http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc" 2>/dev/null  \
#  | awk 'BEGIN { FS= "|"; OFS= "|" }  {print  $1, $2, $5, $10, $11, $13}' \
#   | column -t -s '|'

# Codes my-highlight, my-hilite:
# https://unix.stackexchange.com/questions/46562/how-do-you-colorize-only-some-keywords-for-a-bash-script

SITE="http://webservices.rm.ingv.it/fdsnws/event/1/query?lat=42.35&lon=13.4&maxradius=5.0&starttime=2016-01-01T00:00:00&endtime=2016-12-31T23:59:59&minmag=5&format=text&orderby=time-asc"

curl "$SITE" > data1

awk 'BEGIN { FS= "|"; OFS= "|" }  {print  $1, $5, $10, $11, $13}' data1 |
tee f1 |
column -t -s '|' |
my-highlight -r "Norcia"

pl " Results, hilite:"
awk 'BEGIN { FS= "|"; OFS= "|" }  {print  $1, $5, $10, $11, $13}' data1 |
tee f2 |
column -t -s '|' |
my-hilite -f blue "Norcia"

生産する:

-----
 Results, highlight:
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   788    0   788    0     0   2566      0 --:--:-- --:--:-- --:--:--  2575
#EventID  Depth/Km  MagType  Magnitude  EventLocationName
7073641   8.1       Mw       6.0        1 km W Accumoli (RI)
7076161   8.0       Mw       5.3        5 km E Norcia (PG)
8663031   8.7       Mw       5.4        3 km SW Castelsantangelo sul Nera (MC)
8669321   7.5       Mw       5.9        3 km NW Castelsantangelo sul Nera (MC)
8788671   481.4     ML       5.8        Tirreno Meridionale (MARE)
8863681   9.2       Mw       6.5        5 km NE Norcia (PG)

-----
 Results, hilite:
#EventID  Depth/Km  MagType  Magnitude  EventLocationName
7073641   8.1       Mw       6.0        1 km W Accumoli (RI)
7076161   8.0       Mw       5.3        5 km E Norcia (PG)
8663031   8.7       Mw       5.4        3 km SW Castelsantangelo sul Nera (MC)
8669321   7.5       Mw       5.9        3 km NW Castelsantangelo sul Nera (MC)
8788671   481.4     ML       5.8        Tirreno Meridionale (MARE)
8863681   9.2       Mw       6.5        5 km NE Norcia (PG)

ここでは、mr.spuraticの方法3を使用して色を指定します。後ろに柱化。

読みやすくするためにフィールドを削除し、2つのスクリプトを適用しました(プレフィックスで名前を変更)。私のもの -ここ)スレッドからbashスクリプトの特定のキーワードだけを色付けする方法は? - どちらも文字列を着色する方法で動作します。ノルシア列を実行した後。 (誰が私の投稿に色を表示する方法を教えてくれてありがとう。)

私はこの文字列が出力の他の場所に表示されないと仮定しているので、特定のフィールドは問題ではなく、行全体が一致することを確認します。それ以外の場合、このソリューションはスクリプトに注意を喚起する以外にはほとんど価値がありません。ヒライトそして強調する

これは以下のシステムで行われた。

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
bash GNU bash 4.3.30

スクリプトを使用する場合強調する、spcが必要です(Debianパッケージにあります)。スーパー猫);関連の詳細は次のとおりです。

spc     colorize and print to standard output (man)
Path    : /usr/bin/spc
Package : supercat
Home    : http://supercat.nosredna.net/
Version : 2008
Type    : ELF64-bitLSBexecutable,x86-64,version1(SYSV ...)
Help    : probably available with -h,--help

頑張って...乾杯、drl

答え3

今みんな説明しました。なぜ columnソートされていない出力が表示されるので、もう一度説明しません。

代わりに見せてあげる別のソリューション

column同様の出力を得ることに興味がありますが、カラーコードそして米国国立標準協会エスケープシーケンスを含むバージョンを作成しました。同じ構文(サポートされているフラグの場合)としてcolumnレンダリング出力は予想通りです

私はオンラインでさまざまな解決策を見つけましたが、すべてBashループで動作するため、比較すると非常に遅いです。Perl、私は使用しました。

スクリプトを見つけることができますここ

./column_ansi.sh [--options]直接実行するか()ソースから実行できます(source ./column_ansi.shこの場合、コマンドは次のように使用可能ですcolumn_ansi)。

関連情報