複数行に複数のパターンを配置し、同じ行に印刷

複数行に複数のパターンを配置し、同じ行に印刷

パターンの1つが日付と時刻を含むパターンである別の行のファイル内の情報を見つける方法を見つけようとしています。

以下は入力です

unwantedtext unwantedtext unwantedtext unwantedtext 8/1/2022 6:15 (1st required pattern using date and time format and the date and time can be changed)

unwantedtext unwantedtext unwantedtext unwantedtext 
unwantedtext unwantedtext INC-220721-00007628 (2nd required pattern)

また、2番目のファイルでも、2番目のパターンの一部が常に3行目にあるわけではありませんが、日付と時刻の情報とはまったく異なる行にあります。

2番目のパターンは常にINCで始まり、その後に年、月、日付情報が続きます。

INC

必ずこのINCを最初の3桁に入力してください。

INC-YYMMDD

INCの後に日時が続きます。

INC-YYMMDD-00000000

YYMMDDの後には、任意の8桁の数字が続きます。

-

ハイフンは常に2番目のパターンを区別する役割を果たします。

次のような結果を期待しています

INC-220721-00007628,8/1/2022 6:15 

テストにはWindows CYGWYNを使用し、大量のファイルにはCENTOS 7を使用します。

すべての提案に事前に感謝します。

答え1

値は次のように仮定します。いつもペアでgrep見つけることができ、paste次のものと組み合わせることができます。

$ grep -oP '\b\d{1,2}/\d{1,2}/\d{4} \d{1,2}:\d{2}|INC-\d{6}-\d{8}\b' file | 
  paste -d "," - - 
8/1/2022 6:15,INC-220721-00007628

答え2

grep一人ではできません。おそらくsedPITAを使用してこれを行うことができ、パターンと保存スペースについて現在持っているよりも多くの知識が必要になるでしょう(そして、その知識は他の言語で実行するのが簡単であるため、一般的に学ぶ価値はありません。 )。

簡単に言えば、使用する必要がありますまたは。たとえば、

$ perl -lne 'BEGIN { $, = "," };

             if (m=(\b\d{1,2}/\d{1,2}/\d{4} \d{1,2}:\d{1,2}\b)=) {
               $dt = $1
             } elsif (m/(INC-\d+-\d+)/) {
               print $1, $dt;
               #$dt = ""; # uncomment to clear $dt before next input line
             }' input.txt 
INC-220721-00007628,8/1/2022 6:15

このPerl 1行スクリプトは、Perlの-lオプションを使用して入力を読み取り、出力を印刷している間(\nUnixや\r\nWindowsなど)、行末を自動的に処理します。このオプションはPerlが次のように-n動作するようにしますsed -n-ePerlで実行します。

まず、このスクリプトは出力フィールド区切り文字($,)をコンマに設定します。この変数は次に記録されます。マンパーバールBEGIN {...}各入力行を読み取るたびに1回ではなく、スクリプトの起動時に1回だけ実行されるように、ブロックでこれを行います。

ちなみに、Perlを使うことを選ぶことができます英語秘密の単一文字変数名が気に入らない、または覚えていない場合(use English;スクリプトの内部または-MEnglish1行のコード)、これは長い説明を含む英語のエイリアスとawkに似た対応する名前(該当する場合)にアクセスできます。短い変数。たとえば、awkなどのコマンドをuse English使用できます。すべて同じ意味を持ち、同じ変数を参照します。$,$OUTPUT_FIELD_SEPARATOR$OFS

スクリプトは、Perl の正規表現一致演算子を使用して、目的のパターンを照合し、正規表現の括弧mでキャプチャします。バラよりマンパロップそして「検索してみてください。m/パターン初めて使用するときは、日付パターンからsをエスケープしないように正規表現の区切り文字として使用しましたm=//

マニュアルページも参照してください。フェレ、また必須そしてペレチュート

読み取った各入力行に必要な日付と時刻のパターンと一致しようとし、成功するとキャプチャされた日付と時刻を保存します(Perlのサブパターンの一致変数で、これはタイトル「部分」を見つけて検索するのと似ています$1)。\1sedman perlvar正規表現関連変数")という変数に$dt

以前の一致が失敗した場合は、INC-\d+-\d+パターンの一致を試みます。成功すると、キャプチャされたパターンと$dt変数が印刷されます。

他のすべての入力は無視されます。

またはawkを使用してください:

$ awk -v OFS=, '
  match($0,/\<[[:digit:]]{1,2}\/[[:digit:]]{1,2}\/[[:digit:]]{4} [[:digit:]]{1,2}:[[:digit:]]{1,2}\>/,a) {
    dt = a[0]; next
  };
  match($0,/INC-[[:digit:]]+-[[:digit:]]+/,a) {
    print a[0], dt
  }' input.txt 
INC-220721-00007628,8/1/2022 6:15

awkにはawk変数を設定する便利な-vオプションがあるため、OFSの設定にブロックは必要ありませんBEGIN

このawkの1行の内容はPerlバージョンをほぼ直接翻訳したものですが、match()マッチングとキャプチャテストにawkの機能を使用しています。すべての一致を配列としてキャプチャしますa

また、[[:digit:]]perlに対応するを使用します。多くのロケールでは代わりに\dusingを使用できますが、両方とperlはすべてのロケールで動作します。[0-9][[:digit:]]\d

答え3

grep -Eo 'INC-[[:digit:]]{6}-[[:digit:]]+|[[:digit:]]{1,2}/[[:digit:]]{1,2}/[[:digit:]]{4} [[:digit:]]{1,2}:[[:digit:]]{1,2}' inputfile.txt |
 tr '\n' ',' | 
 sed 's/,$//'

メモ:

  • grep:
    • -o:一致する式のみを取得する
    • -E: 拡張 RE を受け入れる
      • |パターンはパイプ()、ブール演算子「or」で区切られます。

結果:

8/1/2022
INC-220721-00007628

順序は入力ファイルと同じです。

  • tr ...\n改行文字()をコンマ(,)に変換します。

結果:

8/1/2022 6:15,INC-220721-00007628,
  • sed ...:コマンドで追加された最後のtrカンマを検索して置換/削除します。

結果:

8/1/2022 6:15,INC-220721-00007628

答え4

以下を含むpcregrepマルチラインモード:

$ pcregrep -M -o2 -o1 --om-separator=, '(?s) (\d+/\d+/\d+ \d+:\d+) .*?(INC-\d{6}-\d{8})' your-file
INC-220721-00007628,8/1/2022 6:15

関連情報