5

ファイル:

timestamp1 KKIE ABC=123 [5454] GHI=547 JKL=877 MNO=878      
timestamp2 GGHI ABC=544 [ 24548] GHI=883 JKL=587 MNO=874    
timestamp3 GGGIO ABC=877 [3487] GHI=77422 JKL=877 MNO=877    
timestamp4 GGDI ABC=269 [ 1896] GHI=887 JKL=877 MNO=123

注: '[' と次の数字の間にスペースがある場合があります)。

JKL=877 の場合、timestampx、ABC、GHI が必要

解決策 1:

timestamp1 ABC=123 GHI=547
timestamp3 ABC=877 GHI=77422
timestamp4 ABC=269 GHI=887 

解決策 2 (最良の方法):

TIMESTAMP   ABC GHI

timestamp1  123 547

timestamp3  877 77422

timestamp4  269 887

これらの値を個別に取得する方法は知っていますが、すべてを一度に取得することはできません。

A. 解決策 1:

grep JKL=877 file | awk '{print $1}'  
grep JKL=877 file | grep -o '.ABC=[0-9]\{3\}'
grep JKL=877 file | grep -o '.GHI=[0-9]\{3,5\}'

「[」の問題がなければ、次のようにします。

grep JKL=877 | awk '{print $1,$3,$5}' file  

B. ソリューション 2 の場合:

grep JKL=877 file | grep -o '.ABC=[0-9]\{3\}' | tr 'ABC=' ' ' | awk '{print $1}'

(私は awk を使用して、tr 関数によって作成されたスペースを削除します)

grep JKL=877 file | grep -o '.GHI=[0-9]\{3,5\}' | tr 'ABC=' ' ' | awk '{print $1}'

「[」の問題がなければ、次のようにします。

printf "TIMESTAMP       ABC       GHI\n";
awk '{print $1,$3,$5}' file | tr 'ABC=' ' ' | tr 'GHI=' ' ' 

C.すべてを一度にまとめるために、ループを考えて変数に一致を入れていました(https://unix.stackexchange.com/questions/37313/how-do-i-grep-for-multiple-を参照)パターン): MATCH=".ABC=[0-9]\{3\} .GHI=[0-9]\{3,5\}"しかし、私の構文に何か問題があります。さらに、timestampx は含まれません。

printf "TIMESTAMP       ABC       GHI\n"
grep JKL=877 file | while read line
do
?
done 

助けてくれてありがとう。

4

8 に答える 8

6

使ってみてsed

printf "TIMESTAMP\tABC\tGHI\n"

sed -nr '/JKL=877/s/^(\w+).*ABC=([0-9]+).*GHI=([0-9]+).*/\1\t\2\t\3/p' file

出力:

TIMESTAMP   ABC GHI
timestamp1  123 547
timestamp3  877 77422
timestamp4  269 887
于 2013-11-01T18:13:52.657 に答える
2

この種の問題では、通常、名前をname=valueフィールドの型の値にマップする配列を最初に作成するのが最善です。そうすれば、好きな名前で配列をアドレス指定することで、フィールド値を簡単に使用できます。

$ cat file
timestamp1 KKIE ABC=123 [5454] GHI=547 JKL=877 MNO=878
timestamp2 GGHI ABC=544 [ 24548] GHI=883 JKL=587 MNO=874
timestamp3 GGGIO ABC=877 [3487] GHI=77422 JKL=877 MNO=877
timestamp4 GGDI ABC=269 [ 1896] GHI=887 JKL=877 MNO=123
$
$ cat tst.awk
{
    for (i=1;i<=NF;i++) {
        split($i,tmp,/=/)
        val[tmp[1]] = tmp[2]
        fld[tmp[1]] = $i
    }

    if (val["JKL"] == 877) {
        print $1, fld["ABC"], fld["GHI"]
    }
}
$
$ awk -f tst.awk file
timestamp1 ABC=123 GHI=547
timestamp3 ABC=877 GHI=77422
timestamp4 ABC=269 GHI=887
于 2013-11-02T14:11:33.200 に答える
1

を使用:

$ perl -lne '
    print "$1 $2 $3"
        if m/^(timestamp\d+).*?(ABC=\d+).*?(GHI=\d+)\s+JKL=877/i
' file

出力

timestamp1 ABC=123 GHI=547
timestamp3 ABC=877 GHI=77422
timestamp4 ABC=269 GHI=887
于 2013-11-01T19:37:04.403 に答える
0

入力の順序とフィールドの数についていくつかの仮定を立てることができる場合、たとえば最後の行に空白がない場合は、「解決策 2」で試みた単純なフィールド参照を使用できます。

awk '/JKL=877/ { print $1, $4, $(NF==11 ? 7 : 8) }' FS='=| +' file

出力:

timestamp1 123 547            
timestamp3 877 77422
timestamp4 269 887
于 2013-11-04T09:13:40.827 に答える
0

1 行の一致数が一定の場合は、以下の助けを借りて、grep のみのソリューションで解決できますpaste

grep JKL=877 file |
grep -o -e '^timestamp[0-9]' -e '\bABC=[0-9]\{3\}' -e '\bGHI=[0-9]\{3,5\}' |
grep -o '[^=]*$'  |
paste - - -

出力:

timestamp1  123 547
timestamp3  877 77422
timestamp4  269 887

目的のヘッダーを含めるには、次のようにします。

(
  printf "TIMESTAMP\tABC\tGHI\n"
  grep JKL=877 file |
  grep -o -e '^timestamp[0-9]' -e '\bABC=[0-9]\{3\}' -e '\bGHI=[0-9]\{3,5\}' |
  grep -o '[^=]*$'  |
  paste - - -
)

出力:

TIMESTAMP   ABC GHI
timestamp1  123 547
timestamp3  877 77422
timestamp4  269 887
于 2013-11-04T08:47:55.983 に答える