列型データの解析

列型データの解析

いくつかの列形式のデータがありますが、それをさらに形式化したいと思います。次のようになります。

$ getStats | grep ESTABLISHED | column -t
all  tcp  117.54.56.131:80       <-  10.42.100.211:63752   ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752    ->  219.224.67.112:31180  ->                       137.51.59.141:80       ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443      <-  10.42.100.117:59999   ESTABLISHED:ESTABLISHED

デフォルトでは、電話する前にcolumn -tTCPステータス「ESTABLISHED:ESTABLISHED」を1行目と3行目に移動して、2行目に正しく配置するようにしたいと思います。どうすればいいですか?ここでawkとprintfの使用は少し混乱しているようです。デフォルトでは、すべての列を並べ替え、最後の列だけを右揃えにしたいと思います。

答え1

編集1:

1つのアプローチは次のとおりです。

getStats | grep ESTABLISHED | column -t | sed \
-e 's/\(<-\|->\)[ ]\+/\1 /g' \
-e 's/[ ]\+\([^ ]\+$\)/\t\1/' | column -t -s "   "
                                               ^--- TAB
all  tcp  117.54.56.131:80     <- 10.42.100.211:63752                        ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  -> 219.224.67.112:31180  -> 137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <- 10.42.100.117:59999                        ESTABLISHED:ESTABLISHED

まずcolumn -t、空白の後ろのすべての連続した空白を削除し、最後の列を分離して新しい操作を実行します。<-->tabcolumn -t -s '<TAB>'

コマンドラインにある場合:-s" Ctrl+VTAB"(別名tab)asオプションでスペースをタブに置き換えるcolumnことができます。tr

sedジョブとして設定し、スキップgrepやその他の修正:

getStats | column -t | \
sed '/ESTABLISHED/!d;s/\(<-\|->\) */\1  /g;s/ *\([^ ]*\)$/\t \1/' | \
column -t -s "    "
                ^--- TAB

編集2:

awk混乱してもprintfオプションとして残しておきます。このスクリプトを使用すると、次のように話すことができます。

getStats | scrip_name ESTABLISHED

柔軟なカスタマイズなどが可能なのも利点の一つです。

どちらもデータを2回解析するか、データのメタデータを保存して最後に印刷します。

簡単に言えば、これがすることは次のとおりです。

  • 各列の最大幅を記録します。
  • 最大列数を記録します。
  • 各フィールドを行ごとに配列に保存します。
  • 各フィールドを最後に印刷しますが、最後に列の最大幅を使用します。
  • 塗りつぶす最大列数 - 1スペースがあります。
  • 最後のフィールドを印刷します。

(コードと残りのコードの間の分割は、awk -v pat="$1" 'このページのカスタムハイライトHTMLコメントによるものです。)

#!/bin/bash

# Argument 1 is what to match against.
awk -v pat="$1" '
# Iff match pat.
$0 ~ pat {
    # Highest number of columns.
    if (NF > cols)
        cols = NF
    # Increment number of lines.
    ++nl
    # Number of fileds on this line.
    lines[nl] = NF

    for (i = 1; i <= NF; ++i) {
        # IFF not last field and 
        # width of field is > current width of column, store it in wc_a.
        if (i < NF && (wc = length($i)) > wc_a[i])
            wc_a[i] = wc
        # Save columns in array lines[LINE COLUMN]=FIELD_DATA.
        lines[nl,i] = $i
    }
}

END {
    # Loop lines.
    for (i = 1; i <= nl; ++i) {
        # Print all but last.
        for (j = 1; j < lines[i]; ++j)
            printf("%-*s ", wc_a[j], lines[i,j])
        # Print "missing" columns.
        for (; j < cols; ++j)
            printf("%-*s ", wc_a[j], "")
        # Print last column field.
        printf("%s\n", lines[i,lines[i]])
    }
}
' "$2"
# $2 is either file or empty: expect pipe.

古い:

削除され、ここで見つけることができます。

答え2

ここで本当の質問は列数が同じではありません。。一部の行には6つの列があり、一部の行には8つの列があります。

したがって、やるべきことは、欠けているxフィールドとyフィールドに空のフィールドを追加することです(xとyは5と6、3と4のいずれかです)。

次のことができます。

F="\\(\\S\\S*\\)\\s*\\s"
# This is 0160, a nonbreaking space
G=" "

| sed -e "s/^$F$F$F$F$F$F*$/\\1 \\2 \\3 \\4 \\5 $G $G \\6/g" \
| column -t

sed6つのフィールドのみを持つ行を識別し、必要に応じて2つの追加フィールドを追加します。上記のように私は得る。

all  tcp  117.54.56.131:80     <-  10.42.100.211:63752                         ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  ->  219.224.67.112:31180  ->  137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <-  10.42.100.117:59999                         ESTABLISHED:ESTABLISHED

答え3

必要なタスクを実行するPerlスクリプトは次のとおりです。

$ getStats | grep ESTABLISHED | \
perl -ne '
chomp @a;
@a = split(" ",$_);
map { print "$_," } @a[0..4];
if ($a[5] !~ m/>/) {
  map { print " , ,$_," } @a[5..$#a];
  print "\n";
} else {
  map { print "$_," } @a[5..$#a];
  print "\n";
}
' | column -t -s ','

結果は次のとおりです。

all  tcp  117.54.56.131:80     <-  10.42.100.211:63752                         ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  ->  219.224.67.112:31180  ->  137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <-  10.42.100.117:59999                         ESTABLISHED:ESTABLISHED

私はあなたのアプローチに少し異なるアプローチをとり、column -tPerl出力を修正して各フィールドの間にカンマ ","を導入しました。したがって、 `column コマンドより前の出力は次のようになります。

all,tcp,117.54.56.131:80,<-,10.42.100.211:63752, , ,ESTABLISHED:ESTABLISHED,
all,tcp,10.42.120.201:63752,->,219.224.67.112:31180,->,137.51.59.141:80,ESTABLISHED:ESTABLISHED,
all,tcp,77.221.237.24:443,<-,10.42.100.117:59999, , ,ESTABLISHED:ESTABLISHED,

その後、区切り文字の分割をcolumn -t -s ','導きますcolumn。これは単純なスペースよりも処理が簡単です。

一行にカンマを導入するのは私にとってはやや古いですが、この方法は私の役割を果たします。簡単にすることもできますが、実行可能なソリューションです。

関連情報