次の行に特定の一致が含まれていない場合にのみ行を印刷します。

次の行に特定の一致が含まれていない場合にのみ行を印刷します。

完了していない履歴アクティビティのログファイルを取得しようとしています。たとえば、「ID 1234で活動を開始しています...」を記録して成功すると、次の行は「活動1234完了」になります。

その「完了」行が後に出ない「開始...」行を取得しようとしています。

ログファイルの例

Starting activity for ID 1234
ID 1234 completed successfully
Starting activity for ID 3423
ID 3423 completed successfully
Starting activity for ID 9876
ID 9876 completed successfully
Starting activity for ID 99889
ID 99889 completed successfully
Starting activity for ID 10011
ID 10011 completed successfully
Starting activity for ID 33367
Starting activity for ID 936819
ID 936819 completed successfully

この例では、次のような出力が必要です。

Starting activity for ID 33367

…その後に「完了」の行がないからです。

私はこれを使って多くの成功をgrep収めませんでした。awkこれらのツールのいずれかを使用することは可能だと思いますが、私のgrep能力はawkまだ進歩していません。

私に必要な結果を提供するための迅速で信頼性の高いgrepモードを探しています。awk

答え1

代替方法は次のとおりですawk

awk '
  /^Starting/ { I[$5] = $0                  }
  /^ID/       { delete I[$2]                }
  END         { for (key in I) print I[key] }
' infile

出力:

Starting activity for ID 33367

連想配列は、I示されたIDを追跡する。

答え2

sed '$!N;/\n.*completed/d;P;D' <input

これにより、文字列に一致する行が後に来ないすべての入力行が出力から削除されます。十分

答え3

GNU sedを使用してこれを行う方法は次のとおりです。

sed -r 'N; /([0-9]+)\n\w+\s+\1/d; P; D' infile
  • Nパターン空間からさらに1行読みます。
  • 一致する正規表現は同じIDがあることを確認し、そうであればパターンスペース(d)を削除してループを再開します。
  • 一致するものがない場合は、パターンスペースの最初の行を印刷して(P)削除します(D)。

答え4

インストールがpcregrepをサポートしている場合は、複数行(-M)オプションが便利です。

pcregrep -M -o '\AStarting activity for ID (\d+)\n(?!ID \1)' t.z

ID 33367で活動を開始

関連情報