텍스트 파일이 다른 파일의 하위 집합인지 확인하는 방법을 찾으려고합니다.
예를 들면 다음과 같습니다.
foo
bar
의 하위 집합입니다
foo
bar
pluto
동안:
foo
pluto
과
foo
bar
서로의 하위 집합이 아닙니다 …
명령으로 이것을 수행하는 방법이 있습니까?
이 점검은 반드시 교차 점검이어야하며 다음을 반환해야합니다.
file1 subset of file2 : True
file2 subset of file1 : True
otherwise : False
답변
그 파일의 내용이 호출하는 경우 file1
, file2
그리고 file3
apearance의 순서로 당신은 다음과 같은 한 줄에 그것을 할 수 있습니다 :
# 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::Mmap
perl 모듈 과 같이 파일 을 사용하여 해결할 수 있습니다 .
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.txt
및 b.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
하나가 다른 것의 부분 집합이면 스크립트 0
는 True
그렇지 않으면를 반환 합니다 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