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

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

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

foo
bar

의 하위 집합입니다

foo
bar
pluto

동안:

foo
pluto

foo
bar

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

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

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

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


답변

그 파일의 내용이 호출하는 경우 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

답변

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

답변

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

기본적으로 나는 두 개의 파일 테스트입니다 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.


답변

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

}


답변

에서 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