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 :) 로 구성된 행으로 구문 분석하고 -s두 번째 필드( ; 국가) -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가 필요합니다.

관련 정보