テキストファイルが別のテキストファイルのサブセットであるかどうかを確認する方法を見つけようとしています。
例えば:
foo
bar
のサブセットです
foo
bar
pluto
その間:
foo
pluto
そして
foo
bar
お互いのサブセットではない...
コマンドでこれを行う方法はありますか?
このチェックはクロスチェックである必要があり、以下を返す必要があります。
file1 subset of file2 : True
file2 subset of file1 : True
otherwise : False
それらのファイルの内容がfile1
、file2
およびfile3
出現順に、次のワンライナーでそれを行うことができます:
# 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
_を実行することと同じです。その場合、_<>
_は1つのファイルの完全なコンテンツを返します。つまり、スラップモードです。
ファイルの内容を2つの_$h
_および_$n
_変数に格納したら、index()
を使用して、一方が他方にあるかどうかを判断できます。
ただし、これは、ファイル全体がメモリに保存されることを意味します。つまり、この方法は非常に大きなファイルに対しては機能しません。
Mmappableファイル(通常は通常のファイルと、ブロックデバイスなどのシーク可能なファイルが含まれます)の場合、_Sys::Mmap
_ Perlモジュールのように、ファイルでmmap()
を使用することで回避できます。
_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
_
から http://www.catonmat.net/blog/set-operations-in-unix-Shell/ :
Commは、ソートされた2つのファイルを行ごとに比較します。最初に指定されたファイルにのみ現れる行を出力するように実行されるかもしれません。最初のファイルが2番目のファイルのサブセットである場合、1番目のファイルのすべての行が2番目のファイルにも表示されるため、出力は生成されません。
$ comm -23 <(sort subset | uniq) <(sort set | uniq) | head -1 # comm returns no output if subset ⊆ set # comm outputs something if subset ⊊ set
基本的に私はこのスクリプトで2つのファイル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
一方が他方のサブセットである場合、スクリプトはTrue
に対して0
を返し、それ以外の場合は1
を返します。
F1がf2のサブセットである場合、f1-f2は空のセットです。その上に、is_subset関数とそれから派生した関数を書くことができます。 に従って2つのテキストファイルの差を設定
sort_files(){ f1_sorted = "$ 1.sorted" f2_sorted = "$ 2.sorted" もし[! -f $ f1_sorted];次に 猫$ 1 |並べ替え| uniq> $ f1_sorted fi if [! -f $ f2_sorted];次に 猫$ 2 |並べ替え| uniq> $ 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 cat "$ 1.sorted" "$ 2.sorted" |並べ替え| uniq remove_sorted_files $ 1 $ 2 } set_diff(){ sort_files $ 1 $ 2 cat "$ 1.sorted" "$ 2 .sorted "" $ 2.sorted "|並べ替え| uniq -u remove_sorted_files $ 1 $ 2 } rset_diff(){ sort_files $ 1 $ 2 cat "$ 1.sorted" "$ 2.sorted" "$ 1.sorted" |並べ替え| uniq -u remove_sorted_files $ 1 $ 2 } is_subset(){ sort_files $ 1 $ 2 output = $(set_diff $ 1 $ 2) remove_sorted_files $ 1 $ 2 if [-z $ output];その後、 は0を返します。 else は1を返します。 fi }