서로 다른 파일의 두 열을 비교하고 일치하면 인쇄합니다.

서로 다른 파일의 두 열을 비교하고 일치하면 인쇄합니다.

저는 Solaris 10을 사용하고 있으므로 -f와 관련된 grep 옵션이 작동하지 않습니다.

파이프로 구분된 두 개의 파일이 있습니다.

파일 1:

abc|123|BNY|apple|
cab|234|cyx|orange|
def|kumar|pki|bird|

파일 2:

abc|123|
kumar|pki|
cab|234

file2의 처음 두 열을 file1과 비교하고(처음 두 열에서 file1의 전체 내용을 검색) 일치하는 경우 file1의 일치하는 줄을 인쇄하고 싶습니다. 그런 다음 파일 2의 두 번째 줄 등을 검색합니다.

예상 출력:

abc|123|BNY|apple|
cab|234|cyx|orange|

내 파일은 약 400,000줄을 포함하는 대용량이므로 실행 속도를 더 빠르게 만들고 싶습니다.

답변1

이것이 awk의 목적입니다:

$ awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0' file2 file1
abc|123|BNY|apple|
cab|234|cyx|orange|

설명하다

  • -F'|': 필드 구분 기호를 로 설정합니다 |.
  • NR==FNR: NR은 현재 입력 라인 번호이고, FNR은 현재 파일의 라인 번호입니다. 두 파일은 첫 번째 파일을 읽는 경우에만 동일합니다.
  • c[$1$2]++; next: 첫 번째 파일인 경우 처음 두 필드를 c배열로 저장합니다. 그런 다음 첫 번째 파일에만 적용되도록 다음 줄로 이동합니다.

  • c[$1$2]>0: else 블록은 이것이 두 번째 파일인 경우에만 실행되므로 해당 파일의 필드 1과 2가 이미 표시되었는지 확인하고( c[$1$2]>0), 표시된 경우 해당 행을 인쇄합니다. 에서 awk기본 작업은 줄을 인쇄하는 것이므로 c[$1$2]>0true인 경우 줄이 인쇄됩니다.


또는 Perl 태그를 사용하고 있으므로:

perl -e 'open(A, "file2"); while(<A>){/.+?\|[^|]+/ && $k{$&}++};
         while(<>){/.+?\|[^|]+/ && do{print if defined($k{$&})}}' file1

설명하다

첫 번째 줄이 열리고 두 번째 줄( ) file2까지의 모든 내용이 읽혀지고 해시(마지막 일치 연산자의 결과)에 저장됩니다.|.+?\|[^|]+$&%k

두 번째 줄은 동일한 정규식을 사용하여 처음 두 열을 추출하고 해당 줄을 인쇄하는 방식으로 file1을 처리합니다(해당 열이 해시에 정의된 경우) %k.


위의 두 방법 모두 file2의 처음 2개 열을 메모리에 저장해야 합니다. 문제가 되지 않는 행이 수십만 개뿐이지만 그렇다면 그렇게 할 수 있습니다.

cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done

하지만 속도는 느려질 것입니다.

답변2

제 생각에는

grep -Ff file2 file1

이것이 당신이 찾고 있는 것입니다. 작동해야 하지만 원하는 만큼 정확할지는 확신할 수 없습니다. abc|123예를 들어 다른 열의 행에서 발견 되면 file1해당 행도 인쇄됩니다. 이런 일이 발생하지 않는다고 보장할 수 있다면 위의 코드가 작동할 것입니다.

답변3

SQL 용어로 생각하고 싶다면 반드시 '라는 도구를 사용해 보세요.':

$ q -d '|' "select f1.* from file1 f1 join file2 f2 on (f1.c1 = f2.c1 and f1.c2 = f2.c2)"

SQL 쿼리에 익숙하다면 더 명확하고 이해하기 쉬울 것입니다.

답변4

$  sed 's/^/\^/' 2.txt > temp.txt ; grep 1.txt -f temp.txt
abc|123|BNY|apple|
cab|234|cyx|orange|

관련 정보