web-dev-qa-db-ja.com

ANSIエスケープコードを含む入力データを「表化」するためのシェルツール

表にしたいANSIカラーコードを含む入力があります。出力を色付きのままにしておきたいので、表形式の出力はANSIカラーコードを維持する必要があります。したがって、それらを素朴に取り除くことは私の要件を満たしていません。

たとえば、この入力の場合、

\033[0;32;1mgreen_Apple\033[0m 1 100
orange 20 19
pineapple 1000 87
avocado 4 30

私が期待する出力は次のようになります

green_Apple 1    100
orange      20   19
pineapple   1000 87
avocado     4    30

上記の出力では、「green_Apple」は入力からのカラーコードに従って色付けされている必要があります。つまり、緑です。これをどのように達成できるか知りたいのですが。

列を試しましたが、ANSIコードを処理しません。の出力

echo '\033[0;32;1mgreen_Apple\033[0m 1 100
orange 20 19
pineapple 1000 87
avocado 4 30' | column -t

残念ながら

green_Apple  1     100
orange                  20    19
pineapple               1000  87
avocado                 4     30

非表化に注意してください。

3
Jimmy Dean

そのようなコマンドはないと思います。手作業で行う必要があります。何かのようなもの:

awk '
  {
    nf[NR]=NF
    for (i = 1; i <= NF; i++) {
      f[NR,i] = $i
      gsub(/\033\[[0-9;]*[mK]/, "", $i)
      len[NR,i] = l = length($i)
      if (l > max[i]) max[i] = l
    }
  }
  END {
    for (n = 1; n <= NR; n++) {
      for (i = 1; i < nf[n]; i++)
        printf "%s%*s", f[n,i], max[i]+1-len[n,i], ""
      print f[n,nf[n]]
    }
  }'
2

興味のある人のために、私はこのawkスクリプトを StéphaneChazelasの回答 から採用しました。 $PATHにドロップして、コマンドラインから実行できるはずです。

例えば:

> echo -e '\e[32mHello\e[0m,World\nFoo,Bar' | colorcolumn FS=',' OFS=' | '
Hello | World
Foo   | Bar
#!/usr/bin/awk -f
#
# colorcolumn - Like `column`, but works with ANSI colors
#
# Based on this Stack Exchange answer by Stephane Chazelas:
#     https://unix.stackexchange.com/a/121139/259233

{
    nf[NR]=NF
    for (i = 1; i <= NF; i++) {
        cell[NR,i] = $i
        gsub(/\033\[([[:digit:]]+(;[[:digit:]]+)*)?[mK]/, "", $i)
        len[NR,i] = l = length($i)
        if (l > max[i]) max[i] = l
    }
}
END {
    for (row = 1; row <= NR; row++) {
        for (col = 1; col < nf[row]; col++)
            printf "%s%*s%s", cell[row,col], max[col]-len[row,col], "", OFS
        print cell[row,nf[row]]
    }
}
1
Josh Klodnicki

問題はもちろん、columnが印刷文字と非印刷文字を区別しないことです。bashはそのプロンプト(PS1)で\[ \]エスケープ機能を使用してこれを回避します、私はそれを正確に行う他の何も知りません。

問題のあるフィールドが行のstartにあるので、すばやく厄介なハックを試しました。それをthenendですが、一般的なユーティリティを使用して簡単に解決できない同様のパディング/配置の問題が発生します。

ls -l --color | rev | column -t  | rev   # not a useful solution

Perl HTML::FromANSIモジュールをインストールしている場合は、便利なansi2htmlスクリプトがあります。

ls -l --color | ansi2html -f

途中までしか到達できません。HTML出力を調整する必要があります...

HTMLを中間として使用する簡単な(少し重い)ソリューションがあります。HTMLテーブルのレイアウトは、事実上、あなたがやろうとしていることです。

これはAndre Simonansifilter を使用します。例:

ls -l --color | ansifilter -fH

これにより、ANSIシーケンスがHTML(<span style="..."></span>)に変換され、elinksのようなテキストモードのANSI対応ブラウザを使用してダンプできます。

不完全なHTMLが問題になる場合は、オプションで hxclean または htmltidy を実行して、ブラウザに渡す前にHTMLをクリーンアップできます。

ls -l --color  | ansifilter -fH | Perl table.pl | elinks -dump -dump-color-mode 1 

elinksまたはw3mfor this

table.plスクリプトは空白で分割し、関連するHTMLテーブルタグを追加して、目的のフォーマットを実現します。

print "<table>\n";
while (<>) { 
    print "<tr><td>" . 
      join("</td><td>", split(/((?!<[^>]+)\s+(?![^<]+>))/) ) . 
      "</td></tr>\n"; 
}
print "</table>\n";

justは空白で分割せず、 '<' '>'山括弧の内側にない空白で分割するので ' t <span>タグを壊します。これはHTMLを解析するための良い方法ではありませんが、ここでの制約付き入力のタイプには十分なはずです。

デフォルトの色を設定またはオーバーライドする必要がある場合があります(私はそうしました)。これらを~/.elinks/elinks.confファイルに追加します。

set document.colors.use_document_colors = 1
set document.colors.text = "#000000"
set document.colors.background = "#ffffff"

必ず最新(0.12.x)のelinkを使用してください。以前のバージョンはANSIカラー出力をサポートしていません。

1
mr.spuratic

いくつかのsed作業でうまくいくでしょう:

  • sedは、ANSIカラーコードを削除します

    sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
    
  • スペースをタブに置き換えるためのsed

    sed -r "s/\s+/\t/g"
    

最後に:

printf "\033[0;32;1mgreen_Apple\033[0m 1 100
orange 20 19
pineapple 1000 87
avocado 4 30" \
| sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" \
| sed -r "s/\s+/\t/g"

出力:

green_Apple     1           100
orange          20          19
pineapple       1000        87
avocado         4           30

[〜#〜] ps [〜#〜]:私はこれらすべてをls --color outputで正直にテストしました。これは、エコーで遊ぶよりも簡単です。

ANSIカラーコードの削除について:

0
Ouki

フルーツ名に_文字とalphabetic文字のみが含まれていると仮定します。

c='(\e|\\033)\[[0-9;]+m'
sed -r "s/^($c)?([a-zA-Z_]+)($c)?/& \3/" file | column -t | 
sed -r "s/^($c[a-zA-Z_]+$c)( +)([a-zA-Z_]+)/\5\4\1/" |
sed -r "s/^[^ ]+ +//"

出力:

\033[0;32;1mgreen_Apple\033[0m  1     100
orange       20    19
pineapple    1000  87
avocado      4     30

出力をカラーで(テスト)表示するには、シェルコマンド置換を介してパイプラインprintfするだけです。例:

c='(\e|\\033)\[[0-9;]+m'; printf "$(
sed -r "s/^($c)?([a-zA-Z_]+)($c)?/& \3/;" file | column -t | 
sed -r "s/^($c[a-zA-Z_]+$c)( +)([a-zA-Z_]+)/\5\4\1/" |
sed -r "s/^[^ ]+ +//" )"

色付きの出力– onlygreen_Appleは色で表示されます。

green_Apple  1     100
orange       20    19
pineapple    1000  87
avocado      4     30
0
Peter.O