Grepデータのみ(-o)と最初の列

Grepデータのみ(-o)と最初の列

サンプル

wolf@linux:~$ cat data.csv 
A,4.4.4.4,4.4.4.5,4.4.4.6,3.3.3.3,3.3.3.4
B,1.1.1.1,1.1.1.1,1.1.1.2,1.1.1.3,3.3.3.3
C,1.1.1.1,1.1.1.1,1.1.1.1,1.1.1.1,1.1.1.1
D,2.2.2.1,2.2.2.1,2.2.2.2,2.2.2.3,2.2.2.4
wolf@linux:~$ 

このサンプルにはいくつかの重複データがあります。たとえば、3.3.3.3A行とB行に2つあります。

wolf@linux:~$ egrep 3.3.3.3 data.csv 
A,4.4.4.4,4.4.4.5,4.4.4.6,3.3.3.3,3.3.3.4
B,1.1.1.1,1.1.1.1,1.1.1.2,1.1.1.3,3.3.3.3
wolf@linux:~$ 

これで、A,B,C,D最初の列と関連データにのみ興味があります。

私が探すべき4つのデータは次のとおりです。

2.2.2.3
3.3.3.3
4.4.4.4
5.5.5.5

だから私はegrepで|andを使います。-o

wolf@linux:~$ egrep '2.2.2.3|3.3.3.3|4.4.4.4|5.5.5.5' data.csv
A,4.4.4.4,4.4.4.5,4.4.4.6,3.3.3.3,3.3.3.4
B,1.1.1.1,1.1.1.1,1.1.1.2,1.1.1.3,3.3.3.3
D,2.2.2.1,2.2.2.1,2.2.2.2,2.2.2.3,2.2.2.4
wolf@linux:~$ 

出力は良好ですが、データが多すぎます。関連データと最初の列のみが必要です。

だからここに別の試みがあります-o

wolf@linux:~$ egrep -o '2.2.2.3|3.3.3.3|4.4.4.4|5.5.5.5' data.csv
4.4.4.4
3.3.3.3
3,3.3.3
2.2.2.3
wolf@linux:~$ 

これで問題は、最初の列(A/B/C/D)を取得できないことです。

次回試してください

wolf@linux:~$ egrep '2.2.2.3|3.3.3.3|4.4.4.4|5.5.5.5' data.csv | cut -d , -f 1
A
B
D
wolf@linux:~$

最初の列は取得しましたが、データは取得できませんでした。出力を見るとA両方とも何を表すのか3.3.3.34.4.4.4出力に表示されないのでわかりません。

これは実際に私が望む結果ではありません。今私が思うのはこれだ

希望の出力

入力する

2.2.2.3
3.3.3.3
4.4.4.4
5.5.5.5

出力

D       2.2.2.3   
A,B     3.3.3.3
A       4.4.4.4
-       5.5.5.5

残念ながら、今は解決策を思い出していません。助けてください

答え1

$ cat script.awk
NR == FNR {
  a[$0]
  next
}

{
  for (i = 2; i <= NF; i++) {
    for (k in a) {
      if ($i == k) {
        a[k] = a[k] ? a[k] "," $1 : $1
      }
    }
  }
}

END {
  for (k in a) {
    print a[k] "\t" k
  }
}

次のように実行します。

$ cat search.txt
2.2.2.3
3.3.3.3
4.4.4.4
5.5.5.5

$ awk -F, -f script.awk search.txt data.csv
A,B     3.3.3.3
D       2.2.2.3
A       4.4.4.4
        5.5.5.5

答え2

まず、正規表現は2.2.2.3一致するだけでなく(すべての文字に一致する正規表現演算子と同様に)内部的にも一致します。2.2.2.3212.243.22.2.2.36

ここでは以下を使用しますperl

<data.csv perl -F, -lane '
  BEGIN {for (@l = qw{2.2.2.3 3.3.3.3 4.4.4.4 5.5.5.5}) {$v{$_} = []}}
  for (grep $v{$_}, @F[1..$#F]) {push @{$v{$_}}, $F[0]}
  END {for (@l) {print(join(",", @{$v{$_}}) || "-", "\t$_")}}'

これは作る:

D       2.2.2.3
A,B     3.3.3.3
A       4.4.4.4
-       5.5.5.5

項目の質問に答えるにはgrep -o-obtw、非標準拡張として)、出力行の入力行のさまざまな部分を報告するには、次のようにしますpcregrep

<data.csv pcregrep -o1 -o2 --om-separator=$'\t' \
  '^([^,]*).*?,(2\.2\.2\.3|3\.3\.3\.3|4\.4\.4\.4|5\.5\.5\.5)(,|$)'

ただし、これは1行に1単語だけを報告します。ここに与えられた:

A       4.4.4.4
B       3.3.3.3
D       2.2.2.3

を使用してPerlのような正規表現のサポート(BTW、ほとんどの実装では、PCREはPerlのような正規表現のマッチングに使用されるためと同じ)でビルドすると仮定するgrep -Poと、次のことができます。greppcregrep -o

$ grep -Po '^[^,]*+(?=.*?(?1))|((?<![^,])(2\.2\.2\.3|3\.3\.3\.3|4\.4\.4\.4|5\.5\.5\.5)(?![^,]))' data.csv
A
4.4.4.4
3.3.3.3
B
3.3.3.3
D
2.2.2.3

これはfirst-field-provided-there-is-matching-data|matching-data

これは前方予測演算子を使用して実装されprovided-there-is-matching-dataます。(?=...)前提は、次の内容が一致することです。...ここで、(?1)正規表現は最初のキャプチャグループに格納されるため、一致するデータの後には任意の数の文字(.*?)が続きます。

(2\.2\.2\.3|3\.3\.3\.3|4\.4\.4\.4|5\.5\.5\.5)一致するデータの場合は、エスケープにはsを使用します.が、次のようにいくつかのネガティブナビゲーション演算子((?<!...)および(?!...))を使用します。前提は前後の内容ですいいえキャラクター以外のキャラクター,csvフィールドの内容と正確に一致していることを確認してください。

答え3

これを行う簡単な方法は次のとおりです。検索するキーは、key.txtというファイルに1行に1つずつリストされ、検索するデータが引数として配置されるperlコマンドの標準入力に配置されます。

$ < keys.txt \
perl -F, -lane '
  $.==1 && chomp(@keys = <STDIN>);
  $_ .= "$F[0]," for @h{
    grep { my $k = $_; grep(($_ eq $k), @F)} @keys;
  }}{$, = "\t";
  print((($h{$_} //= "-") =~ s/,$//r), $_) for @keys;
' data.csv
D   2.2.2.3
A,B 3.3.3.3
A   4.4.4.4
-   5.5.5.5

答え4

ミラーの使用(https://github.com/johnkerl/miller)と実行

mlr --c2t -N reshape -r "^[^1]$" -o item,value \
then filter '$value=~"(2\.2\.2\.3|3\.3\.3\.3|4\.4\.4\.4|5\.5\.5\.5)"' \
then cut -x -f item \
then nest --implode --values --across-records -f 1 --nested-fs "," \
then reorder -f value data.csv >output

あなたはやる

4.4.4.4 A
3.3.3.3 A,B
2.2.2.3 D

次に、フィルタリストを使用します。

$ cat list
8.8.8.8
2.2.2.3
3.3.3.3
4.4.4.4
5.5.5.5

君は走れるよ

mlr --tsv -N join --ul -j 1 -f list then unsparsify output

持つ

4.4.4.4 A
3.3.3.3 A,B
2.2.2.3 D
8.8.8.8
5.5.5.5

関連情報