grep 出力を長さから幅へ

grep 出力を長さから幅へ

パターンファイルがあり、パターンが見つかったすべての行番号を長い形式/散在形式ではなく、広い形式で返したいと思います。例:

ファイルA.txt

Germany
USA
UK

ファイルB.txt

USA
USA
Italy
Germany
UK
UK
Canada
Canada
Germany
Australia
USA

私は次のことをしました。

grep -nf fileA.txt fileB.txt

これは私に返されます:

1:USA
2:USA
4:Germany
5:UK
6:UK
9:Germany
11:USA

しかし、私は次のようなものが欲しい。

Germany 4 9
USA 1 2 11
UK 5 6

答え1

GNUの使用datamash:

$ grep -n -x -F -f fileA.txt fileB.txt | datamash -s -t : -g 2 collapse 1
Germany:4,9
UK:5,6
USA:1,2,11

まず、行と正確に一致する行grepを取得し、行自体と一致する行番号を出力するために使用されます。fileB.txtfileA.txt

質問に使用されたオプションに加えて、-xandも使用します。私は正規表現()からパターンを読み取ることを防ぎ、-F部分文字列()ではなく行全体を一致させるためにこれをしました。fileA.txt-F-x

次に、datamashユーティリティはそれを:--区切りフィールド(-t :)で構成される行に解析し、-s2番目のフィールド(;国)-g 2で並べ替え、最初のフィールド(collapse 1;行番号)で並べ替えます。各国のリストに縮小します。

tr ':,' '\t\t'その後、明らかにコロンとコンマをタブまたは同様のものに置き換えることができます。

$ grep -n -x -f fileA.txt -F fileB.txt | datamash -s -t : -g 2 collapse 1 | tr ':,' '\t\t'
Germany 4       9
UK      5       6
USA     1       2       11

答え2

使用awk:

awk 'NR==FNR        { country[$0]= country[$0]? country[$0] FS NR: NR; next }
     ($0 in country){ print $0, country[$0] }' fileB fileA

または「数:0ファイルAの国名がファイルBに表示されない場合は、次の手順を実行してください。

awk 'NR==FNR        { country[$0]= country[$0]? country[$0] FS NR: NR; next }
     ($0 in country){ print $0, country[$0]; next } { print $0, "0" }' fileB fileA

答え3

grep コマンド出力を Miller(https://github.com/johnkerl/miller)と実行

grep -nf fileA.txt fileB.txt | \
mlr --c2n --ifs ":" --implicit-csv-header --headerless-csv-output reorder -f 2  then \
nest --implode --values --across-records --nested-fs " " -f 1

あなたはやる

Germany 4 9
USA 1 2 11
UK 5 6

答え4

$ grep -nxFf fileA.txt you fileB.txt   \
| awk -F: '$0 = (length($2) FS $0)' \
| sort -t: -k1,1nr -k3,3 -k2,2n \
| cut -d: -f2- \
| sed -Ee '
  :a
    $!N;y/:/ /
    s/( \S+)\n(.*\1)$/ \2/
  ta
  s/([^\n]*) ([^\n]*)((\n.*)?)$/\2 \1\3/
  P;D
'

出力:

Germany 4 9
USA 1 2 11
UK 5 6

注:\ Sおよび\ n文字クラスが使用されるため、これを実行するにはGNU sedが必要です。

関連情報