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


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

これらのファイルの内容が呼び出された場合file1file2および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 ..あなたの答えはunix-linux固有ではなく、テストした限り私の答えは少し速いので、私の答えを受け入れるかどうかわかりません..あなたはどう思いますか?
gc5 14

もちろん、Unix固有のツールを備えた他のソリューションもあります。しかし、これはPythonのin演算子の良い使い方のようです。
ティモ14

パイピングを組み込んだパイピングを使用して、UnixのようにUnixにするためのPythonコマンドラインラッパーがあります:code.google.com/p/pypこのソリューションを1つのライナーツールのようにUnixにするのは簡単だと思います。
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ます。その場合、<>単一ファイルの完全なコンテンツ、つまり丸lurみモードが返されます

我々は2内のファイルの内容を持っていたら$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

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

基本的に私は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

一方が他方のサブセットである場合、スクリプト0Trueそれ以外の場合に戻ります1


%Lは何をしますか?このスクリプトは機能していないようで、デバッグしようとしています
アレックス

の意味は実際には覚えていませんが%L、それは3年前のことです。From man diff(現在のバージョン)%Lは「行の内容」を意味します。
gc5

%Lは、「新しい」行の内容を出力します。IOW、変更されていない行または古い行については何も印刷しませんが、改行については行の内容を印刷します。
PLG

このスクリプトは、すぐに使用できます。
PLG

2

f1がf2のサブセットである場合、f1-f2は空のセットです。その上で、is_subset関数とそれから派生した関数を作成できます。あたりとして2つのテキストファイル間の差集合


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

  if [!-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" | 並べ替える| ユニック
  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を返す
  そうしないと
    1を返す
  fi

}


このスクリプトは次で始まるべき#!/bin/bashですか?
アレックス

2

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.