1行に複数回表示される正規表現のgrepを作成する方法

1行に複数回表示される正規表現のgrepを作成する方法

正規表現をgrepしたいです。私が探しているパターンが連続して何度も表示されることがあります。パターンが複数回表示される場合は、各項目をカンマで区切って印刷したいと思います。競争のみ新しいファイルに完全な行がありません。印刷したい行に表示されない場合

はい。この正規表現を使用して、[12.123.1.3]パターンの数字を見つけたいと思います。

grep -oh "\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]" 'filename'

入力ファイル(input.txt)

blabla [11.335.2.33] xyuoeretrete [43.22.11.88] jfdfjkfbs [55.66.77.88]
blabla [66.223.44.33]
foo bar
blabla [1.2.33.3] xyuoeretrete [42] bla[1.32.2.4]

新しいファイル(output.csv)の推定結果:

11.335.2.33,43.22.11.88,55.66.77.88
66.223.44.33
n.a.
1.2.33.3,1.32.2.4

注:私はUbuntuを使います。

答え1

そしてperl

perl -lne '
  if (@ips = /\[(\d{1,3}(?:\.\d{1,3}){3})\]/g) {
    print join ",", @ips;
  } else {
    print "n.a.";
  }'

Regexp::Commonまたは、libregexp-common-perlUbuntuなどのDebianベースのシステムのパッケージ内のドットで区切られたクワッドIPv4アドレスの正規表現を使用します。

perl -MRegexp::Common=net -lne '
  if (@ips = /\[($RE{net}{IPv4})\]/g)
    print join ",", @ips;
  } else {
    print "n.a.";
  }'

を使用すると、-nstdinが入力を提供し、パスが追加の引数として提供されているファイルから読み取られたり、などの引数が渡された場合は、いくつかのコマンドの出力から読み取ることができますsome commands|。デフォルトではstdoutとして印刷perlし、(追加)または(ファイルが最初に切り取られずに読み書きモードで開かれることを除いて)printなどのリダイレクト演算子を使用してシェルからファイルにリダイレクトできます。そして、おそらくシェルによってはより多くのものがあります。 。>>>1<>>

入力ファイルの内容を最終的に置き換える出力オプションを追加することもできます-i(そのパスは引数として指定する必要があります)。

ここで、入力は名前付きファイルから取得され、出力input.txtでファイルを上書きまたは生成します。output.csv

< input.txt perl... > output.csv

答え2

FPATでGNU awkを使用する:

awk -v FPAT='\\[([0-9]{1,3}[.]){3}[0-9]{1,3}\\]' -v OFS=, '
{
    $1=$1; print (gsub(/[][]/, "")?$0:"N/A")
}' <infile >output

または、POSIX awkを使用してください(すべて{x,y}RE間隔をサポート)。

awk '
{
    bkup=$0;
    gsub(/\[([0-9]{1,3}[.]){3}[0-9]{1,3}\]/, "|")
    gsub(/[][()\\.{}?+*$^]/, "\\\\&")
    n=split(bkup, tmp, $0)
    for(i=1; i<=n; i++){
        if(tmp[i]!=""){
            gsub(/[][]/, "", tmp[i])
            printf ("%s", (sep?",":"") tmp[i])
            sep=","
        }
    }; print (sep?"":"N/A"); sep=""
}' <infile >output

ファイルに書き込まれた出力output

$ cat output
11.335.2.33,43.22.11.88,55.66.77.88
66.223.44.33
N/A
1.2.33.3,1.32.2.4

2番目の方法では、入力に|および文字を含めないでください。&


インライン記述を含む同じコード:

awk '
{
    #backup from the current record
    bkup=$0;

    #replace desired pattern all with "|" characters 
    #to build regexp patterns of everything other than our desired pattern
    gsub(/\[([0-9]{1,3}[.]){3}[0-9]{1,3}\]/, "|")

    #escape all regexp operators except "|"
    gsub(/[][()\\.{}?+*$^]/, "\\\\&")

    #split the original record (from bkup) into tmp on regexp
    # from the result of the first gsub() above
    n=split(bkup, tmp, $0)

    #loop through the splitted fields on the tmp array
    for(i=1; i<=n; i++){

        #if the current field is not empty
        if(tmp[i]!=""){

            #remove the ], [ characters from it
            gsub(/[][]/, "", tmp[i])

            #and print it (will add comma when it is the second or the next one)
            printf ("%s", (sep?",":"") tmp[i])

            #set comma as the field seperator when at least one field was printed
            sep=","
        }

    #print "N/A" in case there was no field and var "sep" did not set above
    # and then unset the "sep" var
    }; print (sep?"":"N/A"); sep=""

}' <infile >output

答え3

実行可能なawkファイルfilter.awk

#! /usr/bin/awk -f
{
    ret = ""
    line = $0
    while (match(line, /\[([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}\]/) > 0) {
        if (ret != "") {
            ret = ret ","
        }
        ret = ret substr(line, RSTART, RLENGTH)
        line = substr(line, RSTART + RLENGTH)
    }
    if (ret != "") {
        print ret
    }
}

次のように実行します。

./filter.awk filename

答え4

使用幸せ(以前のPerl_6)

値チェックなし:

raku -ne 'if m:g/ ( \d**1..3 )**4 % "." / { $/.join(",").put } else {"n.a.".say};'    

または

raku -ne 'm:g/ ( \d**1..3 )**4 % "." / ?? $/.join(",").put !! "n.a.".say;'  

入力例:

blabla [11.335.2.33] xyuoeretrete [43.22.11.88] jfdfjkfbs [55.66.77.88]
blabla [66.223.44.33]
foo bar
blabla [1.2.33.3] xyuoeretrete [42] bla[1.32.2.4]

サンプル出力(2つの例):

11.335.2.33,43.22.11.88,55.66.77.88
66.223.44.33
n.a.
1.2.33.3,1.32.2.4

少なくともPerl言語系ではmatchgrepではないことを望んでいます。したがって、「グローバル」が一致の複数のインスタンスを返すm/.../ように一致演算子を使用します。これは、要素全体(行など)を返すgrepとは異なります。m:g/.../含む試合]。

\d**1..3つまり、各インスタンス間にピリオドを置き、**44回繰り返される1〜3個の数字()のクラスタを検索し、この正規表現の一致(または)をグローバルに検索します。これは、すべての要素(行など)に対して数値のA一致を取得することを意味します。 .) 最初の一致だけでなく、すべてのインスタンスの場合です。最初の例:find()が一致変数に含まれている場合(例:. 2番目の例:Rakuの三項演算子で使用されているのと同じ一致条件、つまり、一致変数に含まれる一致は条件です。 )または条件がFalseの場合に出力されます。% "."m:globalm:gifput$/elsen.a.condition ?? True !! False??put$/!!n.a.


以下の値を確認してください。

raku -ne 'if m:g/ ( \d**1..3 <?{ $/ < 256 }> )**4 % "." / { $/.join(",").put } else {"n.a.".say};'    

または

raku -ne 'm:g/ ( \d**1..3 <?{ $/ < 256 }> )**4 % "." / ?? $/.join(",").put !! "n.a.".say;'  

入力例:上記と同じ

サンプル出力(2つの例):

43.22.11.88,55.66.77.88
66.223.44.33
n.a.
1.2.33.3,1.32.2.4

上記のRakuコードは、1〜3桁の各クラスタを調べます256。追加の正規表現要素は、一致変数が256未満であることを確認するコードブロックを<?{ $/ < 256 }>含む肯定的なアサーションです。引用する{...}$/ここ

https://raku.org

関連情報