한 파일의 행이 다른 파일의 데이터 하위 집합인지 확인

한 파일의 행이 다른 파일의 데이터 하위 집합인지 확인

file1.txt다음 데이터가 포함된 파일이 있습니다.

MIME_HTML_ONLY
SUSPICIOUS_RECIPS
SORTED_RECIPS
HFILTER_HELO_5

다른 파일에는 file2.txt다음 줄이 있습니다.

HFILTER_FROM_BOUNCE FORGED_OUTLOOK_HTML
SORTED_RECIPS HFILTER_HELO_5
MIME_HTML_ONLY HFILTER_FROM_BOUNCE
SUSPICIOUS_RECIPS ANY_OTHER_WORD
:
:

file2.txt행의 모든 ​​단어가 현재 데이터의 하위 집합인 데이터의 모든 행을 찾고 싶습니다.file1.txt

예를 들어산출위의 내용은 다음 줄이어야 합니다. SORTED_RECIPS HFILTER_HELO_5

이제 개별 행을 반복하고 읽고 file2.txt그것이 의 하위 집합인지 확인할 수 있습니다 file1.txt. 하지만 1000개의 서로 다른 행에 대해 이를 수행해야 합니다 file1.txt's. 따라서 file2.txt모든 행에 대해 루프 를 반복하는 file1.txt것은 매우 느립니다. 이 작업을 수행하는 데 사용할 수 있는 효율적인 방법이 있습니까 awk sed grep?

답변1

awk 'FNR == NR && $0 !~ /^[[:blank:]]*$/ { Dict[$0] = 1 }
     FNR != NR {
        i = 1
        while( i <= NF && Dict[ $i] == 1) i++
        if( i > NF) print
        }
    ' File1.txt File2.txt
  • 보편적이며 file2의 각 줄에 있는 필드/단어 수에 의존하지 않습니다.
  • 두 파일의 정렬된 내용과 정렬되지 않은 내용을 처리합니다.
  • 메모리를 사용하여 첫 번째 파일 로드사전그래서 많은 수의 단어를 검증하고 싶다면 최선이 아닐 수도 있습니다.
  • awk에 제공되는 파일 순서는 필수입니다.
    • 첫 번째는 사전 참조입니다.
    • 기타(최소 1개)는 필터링할 파일입니다.

개념:

  • 값을 인덱스로 사용하여 배열의 각 단어를 로드합니다.
    • 값 1을 사용합니다(할당되지 않은 경우 기본값은 0임).
    • 첫 번째 파일에서 [여기서 FNR(파일 레코드 번호) = NR(파일이 처음 열린 이후의 레코드 번호), 기본적으로 레코드는 awk의 한 줄입니다]
    • 빈 줄에 필터가 있습니다(문자가 없거나 공백만 있음).
  • 카운터 초기화(i)
  • 각 필드(공백 구분 기호로 인해 기본적으로 여기에 있는 단어)를 사전의 해당 필드와 비교합니다. 존재하는 경우(값 = 1) 다음 필드로 루프하고 카운터(i)를 증가시킵니다.
  • 루프 후에 카운터(i)가 필드(단어) 수보다 크면 모든 단어가 일치하고 해당 행을 인쇄합니다.
  • 다음 줄 항목으로 반복

답변2

다음 스크립트 file1.txtgrep -E.

#!/bin/sh
regex="^($(awk '{printf $0"|"}' $1) )+\$"
grep -E "$regex" $2

용법:

$ ./script.sh file1.txt file2.txt 
SORTED_RECIPS HFILTER_HELO_5

$regex다음에서 컴파일됨 file1.txt:

^(ME_HTML_ONLY|SUSPICIOUS_RECIPS|SORTED_RECIPS|HFILTER_HELO_5| )+$

수천 file1.txt, 수백만 줄의 경우 다음 스크립트를 file2.txt사용하여 모든 줄을 단일 awk 프로그램으로 컴파일하는 것이 좋습니다 .file1.txt's

#!/bin/sh
for i; do
        regex="^($(awk '{printf $0"|"}' $i) )+\$"
        echo "/$regex/ { print \"$i: \"\$0 }"
done

예를 들어( file1.txt's이름이 지정됨 match1.txt match2.txt match3.txt):

$ ./script2.sh match*.txt 
/^(ME_HTML_ONLY|SUSPICIOUS_RECIPS|SORTED_RECIPS|HFILTER_HELO_5| )+$/ { print "match1.txt: "$0 }
/^(HFILTER_FROM_BOUNCE|FORGED_OUTLOOK_HTML|ANY_OTHER_WORD| )+$/ { print "match2.txt: "$0 }
/^(SORTED_RECIPS|HFILTER_HELO_5|MIME_HTML_ONLY|HFILTER_FROM_BOUNCE| )+$/ { print "match3.txt: "$0 }

$ ./script2.sh match*.txt >match.awk
$ awk -f match.awk file2.txt 
match2.txt: HFILTER_FROM_BOUNCE FORGED_OUTLOOK_HTML
match1.txt: SORTED_RECIPS HFILTER_HELO_5
match3.txt: SORTED_RECIPS HFILTER_HELO_5
match3.txt: MIME_HTML_ONLY HFILTER_FROM_BOUNCE

관련 정보