파일을 수집할 때 첫 번째 파일에서 일치하지 않는 줄을 수집하려면 어떻게 해야 합니까?

파일을 수집할 때 첫 번째 파일에서 일치하지 않는 줄을 수집하려면 어떻게 해야 합니까?

grep두 파일 사이에 일치하는 줄을 찾는 데 사용합니다 .

grep -w -f file1.txt file2.txt > file3.txt

에서 일치하지 않는 행을 -v제공할 수 있는 플래그가 있다는 것을 알고 있습니다 . 에서 일치하지 않는 행을 가져올 수 있는 방법이 있습니까 ? 각 줄에 더 많은 텍스트가 있기 때문에 위치를 바꾸는 것은 작동하지 않습니다 .file2.txtfile1.txt.file1.txtfile2.txtfile2.txt

기본적으로 file1.txt공백이 없는 단일 ID 열이 있는 텍스트 파일 file2.txt이지만 탭으로 구분된 열과 file1.txt. 그래서 내가 찾으려는 것은 file2.txt일치하는 ID가 없는 행 입니다 file1.txt.

사실 이제 다른 질문에서 답을 찾은 것 같습니다. "Ungrep" - 일치하지 않는 패턴

답변1

이 답변은 @danvoronov의 초기 게시물과 사용되지 않은 키를 얻기 위한 @waltinator의 솔루션을 결합하여 두 가지 모두를 개선한 것입니다.

저는 Princeton CS50 코스 자료의 영어 세트에서 무작위로 선택한 Bash 및 awk 빌딩 테스트 파일 약 60줄을 가지고 있습니다. 나는 또한 단일 프로세스에서 이 문제를 해결하기 위해 30줄의 Bash와 awk를 가지고 있습니다. 성능 개선이 필요해서 아직 공개하지 않겠습니다.

내 스크립트와 아래 게시된 스크립트는 동일한 결과를 생성합니다. 참조 및 검사 목적으로 각 출력 텍스트 앞에는 원본 파일의 줄 번호가 옵니다. 테스트 파일은 file1의 짧은 레코드 15,000개(file2와 일치하는 12,000개, 일치하지 않는 3,000개, 평균 길이 92자)와 file2의 전체 행 20,000개(평균 길이 129자)로 구성됩니다.

키는 행의 임의의 단어로 시작하여 임의의 수의 단어(최소 4개)를 취하는 더 큰 레코드의 무작위 선택에서 가져옵니다.

단일 키가 여러 레코드와 일치할 수 있습니다. 우리는 일대일 페어링을 강요하지 않습니다.

아래 게시된 스크립트는 해당 양의 데이터를 실행하는 데 약 1분 30초가 걸립니다(내 awk는 5분 45초가 걸렸습니다).

file1의 데이터는 유효한 정규식이 아닐 가능성이 높으므로 -F 옵션을 grep과 함께 사용해야 합니다. 일반 텍스트를 RE로 간주하면 * + 와 같은 문자가 많이 있습니다. 예기치 않게 일치하면 ( ) [ ] | 오류가 발생합니다. -F는 더 빠를 수도 있습니다. (600배 향상된 것을 보았습니다. 그 알고리즘이 무엇인지 궁금합니다!)

Unkeyed grep은 -q 옵션만 사용하며 상태는 일치가 발생했는지 여부를 표시합니다. 이렇게 하면 두 개의 프로세스(file1의 각 행에 대한 하위 쉘 및 wc -l)가 절약되고 전체 파일을 읽는 대신 첫 번째 일치 항목에서 종료되므로 읽은 데이터도 평균적으로 절반으로 줄어듭니다.

#! /bin/bash

    grep -n -w -F -f file1.txt file2.txt > file3.txt

    while read -r Key; do
        (( ++Fnr ))
        grep -q -w -F -- "$Key" file2.txt || printf '%d:%s\n' "${Fnr}" "$Key"
    done < file1.txt > file4.txt

일부 초기 질문(필드의 데이터, 공백이 중요한지, 데이터의 크기)이 아직 답변되지 않았으므로 의견을 환영합니다.

답변2

다음 줄을 개별적으로 처리합니다 file1.txt.

for str in $(cat file1.txt) ; do
    num=$(grep -w "$str" file2.txt | wc -l )
    if [[ $num -eq 0 ]] ; then
        echo "$str"
    fi
done

관련 정보