テキスト行の文字列の前後の Grep 変数番号

テキスト行の文字列の前後の Grep 変数番号

テキスト行で数字を探したいです。

cat log.txt | grep "License term"

01/01/2024:00:30 License term is 123 days.

私はこれから「マイナス」を分離したいと思います。キーワードマッチングの前後に単語をエコーする方法はありますか? ""is"の後に文字列を出力します"または""days"の前に文字列を出力します"のように?

おそらく同じように見えますが、今後は変わる可能性があります。 (ログエントリの書式やその他のテキストが追加されます)

答え1

次のコマンドは、正規表現に一致するすべての行、つまり部分文字列を含むすべての行、オプションの正の整数、行の末尾に部分文字列が続くすべての行を検索しますsed。これらの行が見つかった場合は、行全体を整数に置き換え、変更された行を出力して、要求された番号を効果的に抽出します。log.txt.*License term is \([0-9]*\) days\.$License term isdays.

sed -n 's/.*License term is \([0-9]*\) days\.$/\1/p' log.txt

別の方法はを使用することですawk。以下は、文字列を含む行のみを一致させてLicense termから、その行から2番目のスペースで区切られた単語を出力する、やや異なるアプローチです。

awk '/License term/ { print $(NF-1) }' log.txt

明らかに、文字列を含む行からスペースで区切られた5番目のフィールドを削除するためにとgrep組み合わせることもできます。cutLicense term

grep -F 'License term' log.txt | cut -d ' ' -f 5

ここでは、正規表現の代わりに文字列を使用して検索していることを示すために、そのgrepオプションを使用しています。-F

答え2

GNUでは、およびオプションをgrep使用できます。これは、それぞれ「行内の一致部分のみを印刷」と「Perl互換正規表現を使用する」を意味します。 PCREの場合は、「これまで一致するものをすべて削除します」という意味で使用できます。これらすべてを組み合わせると、次のような結果が得られます。-o-P\K

$ grep -oP 'License term is \K\d+' log.txt 
123

もちろん、これが一貫して動作するかどうかは、その中に何があるかによって異なりますが、log.txtあなたの例では動作します。

答え3

pcre2grep(または以前のバージョン)でpcregrep

pcre2grep -xo1 '\d\d/\d\d/\d\d\d\d:\d\d:\d\d License term is (\d+) days\.' < log.txt

行は保守的に一致し、実際にパターンに一致する行のみを選択し、そこxから最初のoキャプチャグループに一致する数が出力されます。1

pまたはPerl(in pcre2grep)と同じです。

perl -lne '
  print $1 if m{^\d\d/\d\d/\d\d\d\d:\d\d:\d\d License term is (\d+) days\.$}
  ' < log.txt

答え4

使用幸せ(以前のPerl_6)

~$ raku -ne '.put if s/ .* "License term is " (<[0..9]>*) " days." $/$0/;'  log.txt   

#OR:

~$ raku -ne '.put if s/ .* License \s term \s is \s (<[0..9]>*) \s days \. $/$0/;'  log.txt

#OR:

~$ raku -ne '.put if s/ .* License <.ws> term <.ws> is <.ws>  (<[0..9]>*) <.ws> days \. $/$0/;'  log.txt

または:

~$ raku -ne 'if /License \s term/ { put .words[4] };'  log.txt

#OR:

~$ raku -ne 'put .words[4]  if /License \s term/;'   log.txt

または:

~$ raku -e '$0.put for lines.match(/ "License term is "  ( \d+ ) /);'  log.txt 

#OR:

~$ raku -e '.put for lines.match(/ "License term is "  ( \d+ ) /);'  log.txt  

Rakuで書かれた答えは、すでに公開されている優れた答えと多くの点で似ていますsedawk最初の2つの回答セットは、-ne自動印刷されない限り、1行ずつフラグを使用します。最初のグループではs///このフォームを使用してください。 2番目のグループでは、words空白を分割するためにRakuのルーチンが使用されます。最後の回答セットでは、Rakuにlinesサブキーを検索または返すルーチンがありますmatch

入力例:

#dummy_line followed by blank line

01/01/2024:00:30 License term is 123 days.
#dummy_line

出力例:

123

Raku正規表現エンジンを使用すると、キャプチャタグとプレビュー/後ろ向きも使用できます。詳しくは、下記の最初のリンクをご覧ください。また、<[0..9]>ASCII番号または\dASCII + Unicode番号をキャプチャすることもできます。

https://docs.raku.org/言語/regexes#Regexes
https://raku.org

関連情報