패턴 파일이 있고 패턴이 발견된 모든 줄 번호를 긴 형식/흩어진 형식이 아닌 넓은 형식으로 반환하고 싶습니다. 예:
파일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.txt
fileA.txt
질문에 사용된 옵션 외에도 -x
and 도 사용합니다. 정규식( )에서 패턴을 읽는 것을 방지 -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가 필요합니다.