発生回数を見つけ、最初の結果のフラグメントで次の発生を見つけます。

発生回数を見つけ、最初の結果のフラグメントで次の発生を見つけます。

私は少し助けを求めて、進行中に学んでいます。以下のようなものがあります。何が起こるのか見せたい「ログイン」Log1から「処理された請求書」ログ1に。検索値の使用 - 44.正直なところ、私はテストのようなものをだまそうとしているように見えますが、そうではありません。私はファイルを分解して学ぶことを望むのが初めてです。

ファイル.txt

Log0 | 20191104 | 01 | Logged In - 55
Log1 | 20191104 | 04 | Logged In - 44
Log2 | 20191104 | 03 | Logged In - 33
Log1 | 20191104 | 02 | Received Bill
Log1 | 20191104 | 02 | Accepted Bill
Log2 | 20191104 | 05 | Logged Out - 33
Log1 | 20191104 | 33 | Processed Bill
Log0 | 20191104 | 44 | Broken Bill

目的の出力を見つけます。

Log1 | 20191104 | 04 | Logged In - 44
Log1 | 20191104 | 33 | Processed Bill

答え1

Perlソリューション:

perl -F'/\|/' -ne '$id = $F[0] if $F[3] =~ /- 44$/;
                   print if $F[0] eq $id && $F[3] =~ /Logged In|Processed Bill/;
                  ' -- file.txt
  • -n入力を1行ずつ読みます。
  • -F与えられた正規表現の各入力行を配列@Fに分割します。
  • つまり$F[3]、4番目の列が一致すると、- 44最初の列がに保存されます$id
  • $id最初の列が同じで、4番目の列がまたはに一致Logged Inする場合は、Processed Bill行全体を印刷します。

答え2

実際には@Chorobaソリューションと非常によく似ています。

awk -F'|'   '/Logged In/                   { login[$1]=$0}     
             /Processed Bill/ && login[$1] { print login[$1]; print}' ex1

どこ:

  • /Logged In/ { login[$1]=$0}- 列1に関連付けられている「ログイン」行を保存します(例:「Log1」)。
  • /Processed Bil/ && login[$1] {print ...}- 以前にログインした「処理済み請求書」が見つかったら印刷します。

修正:44のみ印刷します。

awk -F'|'   '/Logged In - 44/              { cod=$1; line=$0}     
             /Processed Bill/ && $1==cod   { print line "\n" $0}' file

答え3

Gnu sedが拡張正規表現モードの場合:

$ sed -re ':a
    /Logged In - 44/!d
    $d;h;N
    /^(\S+)\s*\|.*\n\1\s*\|.*Processed Bill/b
    g;ba
' file

結果

Log1 | 20191104 | 04 | Logged In - 44
Log1 | 20191104 | 33 | Processed Bill

どのように動作しますか?

° Skip lines till we meet "Logged In 44"
° Pick up the nexr line and if it is "Processed Bill" AND first field matches with the logged in line, then it's a GO.
° Otherwise, discard the second portion and redo this process. 
° Assumption is that logged in 44 line is unique. 

関連情報