텍스트 파일이 다른 파일의 하위 집합인지 확인하는 방법


12

텍스트 파일이 다른 파일의 하위 집합인지 확인하는 방법을 찾으려고합니다.

예를 들면 다음과 같습니다.

foo
bar

의 하위 집합입니다

foo
bar
pluto

동안:

foo
pluto

foo
bar

서로의 하위 집합이 아닙니다 ...

명령으로 이것을 수행하는 방법이 있습니까?

이 점검은 반드시 교차 점검이어야하며 다음을 반환해야합니다.

file1 subset of file2 :    True
file2 subset of file1 :    True
otherwise             :    False

잠재적으로 더 효율적인 솔루션 (파일도 주문한 경우) : github.com/barrycarter/bcapps/blob/master/…
barrycarter

답변:


11

그 파일의 내용이 호출하는 경우 file1, file2그리고 file3apearance의 순서로 당신은 다음과 같은 한 줄에 그것을 할 수 있습니다 :

 # python -c "x=open('file1').read(); y=open('file2').read(); print x in y or y in x"
 True
 # python -c "x=open('file2').read(); y=open('file1').read(); print x in y or y in x"
 True
 # python -c "x=open('file1').read(); y=open('file3').read(); print x in y or y in x"
 False

귀하의 답변에 감사드립니다 .. +1 .. 귀하의 답변은 유닉스 리눅스에 국한되지 않았으며 테스트 한 한 내 답변이 약간 빠르기 때문에 답변을 수락할지 모르겠습니다.
gc5

물론 유닉스 전용 툴을 갖춘 다른 솔루션도 있습니다. 그러나 이것은 파이썬 in연산자를 잘 사용하는 것 같습니다 .
Timo

pyp : code.google.com/p/pyp 라는 이름의 파이핑이 내장 된 파이썬 명령 줄 래퍼가 있습니다.
IBr

3

perl:

if perl -0777 -e '$n = <>; $h = <>; exit(index($h,$n)<0)' needle.txt haystack.txt
then echo needle.txt is found in haystack.txt
fi

-0octal레코드 분리 문자를 정의합니다. 8 진수가 0377 (최대 바이트 값)보다 크면 분리 문자가 없음을 의미하며 이는 것과 같습니다 $/ = undef. 이 경우 <>단일 파일의 전체 내용을 반환 합니다 . 이것이 slurp 모드 입니다.

우리는 두 가지의 파일의 내용을 일단 $h$n변수를 우리가 사용할 수있는 index()하나가 다른에서 찾을 수 있는지 확인.

그러나 전체 파일이 메모리에 저장되어 있기 때문에 매우 큰 파일에는 방법이 작동하지 않습니다.

mmappable 파일 (일반적으로 일반 파일 및 블록 장치와 같이 검색 가능한 대부분의 파일 포함)의 mmap()경우 Sys::Mmapperl 모듈 과 같이 파일 을 사용하여 해결할 수 있습니다 .

if 
  perl -MSys::Mmap -le '
    open N, "<", $ARGV[0] || die "$ARGV[0]: $!";
    open H, "<", $ARGV[1] || die "$ARGV[1]: $!";
    mmap($n, 0, PROT_READ, MAP_SHARED, N);
    mmap($h, 0, PROT_READ, MAP_SHARED, H);
    exit (index($h, $n) < 0)' needle.txt haystack.txt
then
  echo needle.txt is found in haystack.txt
fi

2

이 질문 덕분에 해결책을 찾았습니다.

기본적으로 나는 두 개의 파일 테스트입니다 a.txtb.txt이 스크립트 :

#!/bin/bash

first_cmp=$(diff --unchanged-line-format= --old-line-format= --new-line-format='%L' "$1" "$2" | wc -l)
second_cmp=$(diff --unchanged-line-format= --old-line-format= --new-line-format='%L' "$2" "$1" | wc -l)

if [ "$first_cmp" -eq "0" -o "$second_cmp" -eq "0" ]
then
    echo "Subset"
    exit 0
else
    echo "Not subset"
    exit 1
fi

하나가 다른 것의 부분 집합이면 스크립트 0True그렇지 않으면를 반환 합니다 1.


% L은 무엇을합니까? 이 스크립트는 작동하지 않는 것 같습니다, 그리고 그것을 디버깅하려고합니다 ...
Alex

나는 실제로 %L3 년 전의 의미를 기억하지 못합니다 . From man diff(현재 버전) %L은 "행 내용"을 의미합니다.
gc5

% L은 "new"줄의 내용을 인쇄합니다. IOW, 변경되지 않은 줄이나 오래된 줄에는 아무것도 인쇄하지 말고 줄 바꿈 내용은 줄 바꾸기를 위해 인쇄하십시오.
PLG

이 스크립트는 즉시 사용할 수 있습니다!
PLG

2

f1이 f2의 부분 집합 인 경우 f1-f2는 빈 세트입니다. 이를 바탕으로 is_subset 함수와 그 함수를 작성할 수 있습니다. 두 개의 텍스트 파일 간의 설정 차이에 따라


sort_files () {
  f1_sorted = "$ 1.sorted"
  f2_sorted = "$ 2.sorted"

  만약 [ ! -f $ f1_sorted]; 그때
    고양이 $ 1 | 정렬 | 유니크> $ f1_sorted
  fi

  만약 [ ! -f $ f2_sorted]; 그때
    고양이 $ 2 | 정렬 | 유니크> $ f2_sorted
  fi
}

remove_sorted_files () {
  f1_sorted = "$ 1.sorted"
  f2_sorted = "$ 2.sorted"
  rm -f $ f1_sorted
  rm -f $ f2_sorted
}

set_union () {
  sort_files $ 1 $ 2
  고양이 "$ 1.sorted" "$ 2.sorted"| 정렬 | 유니크
  remove_sorted_files $ 1 $ 2
}

set_diff () {
  sort_files $ 1 $ 2
  고양이 "$ 1.sorted" "$ 2.sorted" "$ 2.sorted"| 정렬 | 유니크 -u
  remove_sorted_files $ 1 $ 2
}

rset_diff () {
  sort_files $ 1 $ 2
  고양이 "$ 1.sorted" "$ 2.sorted" "$ 1.sorted"| 정렬 | 유니크 -u
  remove_sorted_files $ 1 $ 2
}

is_subset () {
  sort_files $ 1 $ 2
  출력 = $ (set_diff $ 1 $ 2)
  remove_sorted_files $ 1 $ 2

  만약 [-z $ output]; 그때
    0을 반환
  그밖에
    1을 반환
  fi

}


이 스크립트는 #!/bin/bash?로 시작해야합니까 ?
Alex

2

에서 http://www.catonmat.net/blog/set-operations-in-unix-shell/ :

Comm은 두 개의 정렬 된 파일을 한 줄씩 비교합니다. 처음 지정된 파일에만 나타나는 행을 출력하는 방식으로 실행될 수 있습니다. 첫 번째 파일이 두 번째 파일의 하위 집합 인 경우 첫 번째 파일의 모든 줄도 두 번째 파일에 나타나므로 출력이 생성되지 않습니다.

$ comm -23 <(sort subset | uniq) <(sort set | uniq) | head -1
# comm returns no output if subset ⊆ set
# comm outputs something if subset ⊊ set
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.