web-dev-qa-db-ja.com

テキストファイルが別のファイルのサブセットであるかどうかを知る方法

テキストファイルが別のテキストファイルのサブセットであるかどうかを確認する方法を見つけようとしています。

例えば:

foo
bar

のサブセットです

foo
bar
pluto

その間:

foo
pluto

そして

foo
bar

お互いのサブセットではない...

コマンドでこれを行う方法はありますか?

このチェックはクロスチェックである必要があり、以下を返す必要があります。

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

それらのファイルの内容がfile1file2および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
11
Timo

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
_
3

から 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
Alec

この質問のおかげで解決策を見つけました

基本的に私はこのスクリプトで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

一方が他方のサブセットである場合、スクリプトはTrueに対して0を返し、それ以外の場合は1を返します。

2
gc5

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 
 
} 
 
2
Saurabh Hirani