모든 파일 줄이 다른 파일에서 발생하는지 확인


14

나는 2 개의 파일을 가지고 있습니다 : file1은 약 10 000 줄이고 file2는 몇 백 줄입니다. file2의 모든 줄이 file1에서 발생하는지 확인하고 싶습니다. 즉 : ∀ line ℓ ∈ file2 : ℓ ∈ file1

이 기호의 의미 또는 "file2의 모든 행이 file1에서 발생하는지 확인"의 의미를 모르는 경우 다음 중 하나를 의미합니다. 두 파일 중 하나의 동등한 행은 파일이 요구 사항을 충족하는지 여부를 확인하는 데 영향을 미치지 않습니다.

어떻게해야합니까?


2
해당 파일에 중복 줄이있을 수 있습니까? file22 줄을 포함하는 경우 2 줄 이상을 포함 A해야 합니까? file1A
Stéphane Chazelas

2
@ StéphaneChazelas 모든 파일 (두 파일 모두)은 고유해야합니다.
UTF-8

1
@ UTF-8 질문을 편집하는 데 중요한 세부 사항이 될 것입니다.
David Z

2
@DavidZ 기존 답변이 그 보증에 의존하지 않기 때문에 더 이상은 아닙니다. 그래서 지금 질문을 편집함으로써 대답의 명백한 범위를 줄일 것입니다.
UTF-8

@ UTF-8 질문이 없어도 조금 모호하지만, 예를 들어 주어진 줄이 file2에서 5 번 발생하는 경우 해당 줄도 file1에서 5 번 발생해야합니까 (한 번만 반대)? 그 요구 사항이 있다면 기존 답변이 효과가있는 것처럼 보이지 않으므로 적어도 당신이 의미하는 것이 아닌 것을 분명히하는 무언가를 편집하는 것이 좋습니다.
David Z

답변:


18
comm -13 <(sort -u file_1) <(sort -u file_2)

이 명령은 고유 한 행을 출력합니다 file_2. 따라서 출력이 비어 있으면 모든 file_2줄이에 포함됩니다 file_1.

통신의 남자에서 :

   With  no  options,  produce  three-column  output.  Column one contains
   lines unique to FILE1, column two contains lines unique to  FILE2,  and
   column three contains lines common to both files.

   -1     suppress column 1 (lines unique to FILE1)

   -2     suppress column 2 (lines unique to FILE2)

   -3     suppress column 3 (lines that appear in both files)

@don_crissti 맞습니다. 고정 : -u옵션이 sort명령에 추가되었습니다 . 이제는 정렬 된 두 파일에 고유 한 행만 남습니다.
MiniMax

놀랍도록 간단하게 솔루션! 이 구문은 파일이 필요한 모든 프로그램에 적용 가능합니까? 나는 항상 <파이프를 stdin에 넣었다고 생각했다 . 대괄호 용어가이를 변경합니까?
UTF-8

2
@ UTF-8 프로세스 대체 라고 합니다. 여기에서 읽을 수 있습니다 . 예, 임시 파일처럼 동작하므로 파일을 기대하는 모든 프로그램에서 실제 파일 대신 사용할 수 있습니다.
MiniMax

이것이 자주하는 일이라면 미리 file_1정렬 된 형태 로 저장하는 것이 좋습니다 . 타이핑과 시간을 모두 절약합니다.
Stig Hemmer

7
@minimax "any"를 제외한 좋은 의견. 결과 "파일"은 실제 파일이 아닌 스트림이므로 프로세스 대체는 훌륭하지만 모든 경우에 사용할 수는 없습니다. 즉, 일반 파일과 같이 "검색 가능"하지 않으며 프로그램이 처음부터 파일을 정상적으로 읽을 때만 사용할 수 있으며 프로그램이 특정 지점을 찾는 것과 같은 일부 파일 전용 기능을 사용하는 경우에는 사용할 수 없습니다. 처음부터 다시 되감기. 행복하게도 대부분의 프로그램은 단순히 파일을 읽기 ()하기 때문에 프로세스 대체는 대부분의 프로그램에서 작동하지만 "모든"프로그램에서는 작동하지 않습니다.
Law29

7
[ $(grep -cxFf file2 <(sort -u file1)) = $(sort -u file2 | wc -l) ] && 
  echo all there || 
  echo some missing

file1 (file의 고유 행)에서 일치하는 파일 수가 file2의 고유 행 수와 일치하면 모두 존재합니다. 그렇지 않으면 그렇지 않습니다.


5

GNU awk가 특정 length(array)기능 (및 awk지원할 수있는 다른 구현)을 지원하고 파일을 정렬 할 경우 필요하지 않은 곳에서 사용합니다.

gawk 'FNR==NR{seen[$0];next} ($0 in seen){delete seen[$0]};
    END{print (!length(seen))?"Matched":"Not Matched"}' file2 file1

이것은 판독되는 파일 2을 라는 배열 seen의 전체 행과 키 파일 2 .

그런 다음 file1을 읽고 배열의 행과 일치하면 각 행에 대해 해당 키를 삭제하십시오.

배열이 비어 있으면 마지막에 file2의 모든 행 이 file1에 존재 하고 인쇄 Matched되고 그렇지 않으면 표시됩니다 Not Matched.


모든 awk구현 에서 호환성 .

awk 'FNR==NR{seen[$0];next} ($0 in seen){delete seen[$0]};
    END{for(x in seen);print (!x)?"Matched":"Not Matched"}' file2 file1

file2에있는 경우에만 빈 줄 또는 공백이있는 줄을 무시하려면 배열에서 읽지 않는 NF조건 을 추가해야합니다 NR==FNR && NF {....


length(array)gawk-only AFAIK입니다. 확실히 POSIX가 아닙니다.
dave_thompson_085

@ dave_thompson_085 맞습니다. 답변을 업데이트했습니다. 감사
αғsнιη

3

를 사용 comm하면 두 파일에서 공통 인 줄을 찾을 수 있습니다.

comm -12 file1 file2

man comm자세한 내용을 살펴보십시오


두 파일 모두에서 공통 줄을 반환한다고 수정하지만 file1에 종료되지 않는 file2에 줄이 있으면 file2의 모든 줄이 file1에 존재하지 않는 OP의 Q에 대한 답변을 제공하지 않습니다.
αғsнιη

1
파일을 정렬해야합니다. man "에서 comm-두 개의 정렬 된 파일을 한 줄씩 비교"
MiniMax

@MiniMax가 맞습니다. 작동하지 않습니다. 다른 대답 comm은 분명히 틀린 해결책을 포함합니다. 명령을 실행할 때 파일이 정렬 순서가 아니며 두 파일에 모두 많은 줄이 있다는 경고가 표시됩니다.
UTF-8

3
diff -q <(sort -u file2) <(grep -Fxf file2 file1 | sort -u)

경우에는 출력을 생성하지 않습니다 file1포함 모든 라인file2상태와 종료 0그렇지 않으면 뭔가를 인쇄합니다,

Files /proc/self/fd/11 and /proc/self/fd/12 differ

상태로 종료 1


2

파이썬 프로그램을 사용하십시오 :

#!/usr/bin/env python3
import sys

def open_arg(path):
    return sys.stdin if path == '-' else open(path)

def strip_linebreak(s):
    return s[:-1] if s.endswith('\n') else s

with open_arg(sys.argv[1]) as pattern_file:
    patterns = set(map(strip_linebreak, pattern_file))

with open_arg(sys.argv[2]) as dataset_file:
    for l in map(strip_linebreak, dataset_file):
        patterns.remove(l)
        if not patterns:
            break

sys.exit(int(bool(patterns)))

용법:

python3 contains-all.py file2 file1

프로그램 종료 상태는 파일 2의 모든 패턴이 일치했는지 여부를 나타냅니다.

  • 0 (성공)은 모든 패턴이 일치했음을 의미합니다.
  • 1 (실패)은 일부 패턴이 일치하지 않음을 의미합니다.

쉘 (스크립트)에서 종료 상태를 쿼리하려면 $?특수 변수 또는 명령 종료 상태를 평가하는 다른 표현식 (예 : 단락 연산자 &&및 또는 ||과 같은 조건식)을 사용할 수 있습니다. 예:ifwhile

if python3 compare-all.py file2 file1 && some-other --condition; then
    # do stuff
fi

1

combine에서 moreutils는 당신에게 모든 라인이 표시됩니다에 file2그에없는 file1과 :

combine file2 not file1

그런 다음 다음 wc -l과 같이 배관하여 줄 수를 계산할 수 있습니다 .

if [ $(combine file2 not file1 | wc -l) != 0 ]; then
  echo "lines missing"
else
  echo "You're fine"
fi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.