ファイルをセットとして扱い、それらに対してセット操作を実行するように特別に設計されたLinuxツールを知っている人はいますか?違いや交差点などは?
要素がNULおよび改行以外の文字列であると仮定すると(ただし、改行はファイル名で有効であることに注意してください)、setをテキストファイルとして表すことができます。 1行に1つの要素があり、いくつかの標準Unixユーティリティを使用します。
$ grep -Fxc 'element' set # outputs 1 if element is in set
# outputs >1 if set is a multi-set
# outputs 0 if element is not in set
$ grep -Fxq 'element' set # returns 0 (true) if element is in set
# returns 1 (false) if element is not in set
$ awk '$0 == "element" { s=1; exit }; END { exit !s }' set
# returns 0 if element is in set, 1 otherwise.
$ awk -v e='element' '$0 == e { s=1; exit } END { exit !s }'
$ comm -12 <(sort set1) <(sort set2) # outputs intersect of set1 and set2
$ grep -xF -f set1 set2
$ sort set1 set2 | uniq -d
$ join -t <(sort A) <(sort B)
$ awk '!done { a[$0]; next }; $0 in a' set1 done=1 set2
$ cmp -s <(sort set1) <(sort set2) # returns 0 if set1 is equal to set2
# returns 1 if set1 != set2
$ cmp -s <(sort -u set1) <(sort -u set2)
# collapses multi-sets into sets and does the same as previous
$ awk '{ if (!($0 in a)) c++; a[$0] }; END{ exit !(c==NR/2) }' set1 set2
# returns 0 if set1 == set2
# returns 1 if set1 != set2
$ awk '{ a[$0] }; END{ exit !(length(a)==NR/2) }' set1 set2
# same as previous, requires >= gnu awk 3.1.5
$ wc -l < set # outputs number of elements in set
$ awk 'END { print NR }' set
$ sed '$=' set
$ comm -23 <(sort -u subset) <(sort -u set) | grep -q '^'
# returns true iff subset is not a subset of set (has elements not in set)
$ awk '!done { a[$0]; next }; { if !($0 in a) exit 1 }' set done=1 subset
# returns 0 if subset is a subset of set
# returns 1 if subset is not a subset of set
$ cat set1 set2 # outputs union of set1 and set2
# assumes they are disjoint
$ awk 1 set1 set2 # ditto
$ cat set1 set2 ... setn # union over n sets
$ sort -u set1 set2 # same, but doesn't assume they are disjoint
$ sort set1 set2 | uniq
$ awk '!a[$0]++' set1 set2 # ditto without sorting
$ comm -23 <(sort set1) <(sort set2)
# outputs elements in set1 that are not in set2
$ grep -vxF -f set2 set1 # ditto
$ sort set2 set2 set1 | uniq -u # ditto
$ awk '!done { a[$0]; next }; !($0 in a)' set2 done=1 set1
$ comm -3 <(sort set1) <(sort set2) | tr -d '\t' # assumes not tab in sets
# outputs elements that are in set1 or in set2 but not both
$ sort set1 set2 | uniq -u
$ cat <(grep -vxF -f set1 set2) <(grep -vxF -f set2 set1)
$ grep -vxF -f set1 set2; grep -vxF -f set2 set1
$ awk '!done { a[$0]; next }; $0 in a { delete a[$0]; next }; 1;
END { for (b in a) print b }' set1 done=1 set2
セットのすべての可能なサブセットは、1行に1つずつ、スペースで区切られて表示されます。
$ p() { [ "$#" -eq 0 ] && echo || (shift; p "$@") |
while read r; do printf '%s %s\n%s\n' "$1" "$r" "$r"; done; }
$ p $(cat set)
(要素にSPC、TAB($IFS
のデフォルト値を想定)、バックスラッシュ、ワイルドカード文字が含まれていないと想定)。
$ while IFS= read -r a; do while IFS= read -r b; do echo "$a, $b"; done < set1; done < set2
$ awk '!done { a[$0]; next }; { for (i in a) print i, $0 }' set1 done=1 set2
$ comm -12 <(sort set1) <(sort set2) # does not output anything if disjoint
$ awk '++seen[$0] == 2 { exit 1 }' set1 set2 # returns 0 if disjoint
# returns 1 if not
$ wc -l < set # outputs 0 if the set is empty
# outputs >0 if the set is not empty
$ grep -q '^' set # returns true (0 exit status) unless set is empty
$ awk '{ exit 1 }' set # returns true (0 exit status) if set is empty
$ sort set | head -n 1 # outputs the minimum (lexically) element in the set
$ awk 'NR == 1 { min = $0 }; $0 < min { min = $0 }; END { print min }'
# ditto, but does numeric comparison when elements are numerical
$ sort test | tail -n 1 # outputs the maximum element in the set
$ sort -r test | head -n 1
$ awk '$0 > max { max = $0 }; END { print max }'
# ditto, but does numeric comparison when elements are numerical
すべては http://www.catonmat.net/blog/set-operations-in-unix-Shell-simplified/ で入手できます
ちょっと。自分でソートする必要がありますが、comm
を使用して各行をセットメンバーとして処理できます:交差の場合は-12
、差の場合は-13
。 (そして-23
を使用すると、違いが反転します。つまり、set2 - set1
ではなくset1 - set2
になります。)この設定では、Unionはsort -u
です。
16.10以降、小さなコンソールツール「setop」がDebian StretchとUbuntuで利用できるようになりました。 _Sudo apt install setop
_から取得できます
下記は用例です。操作されるセットは、異なる入力ファイルとして与えられます:_setop input # is equal to "sort input --unique" setop file1 file2 --union # option --union is default and can be omitted setop file1 file2 file3 --intersection # more than two inputs are allowed setop file1 - --symmetric-difference # ndash stands for standard input setop file1 -d file2 # all elements contained in 1 but not 2
_
ブールクエリは、trueの場合は_EXIT_SUCCESS
_のみを返し、そうでない場合は_EXIT_FAILURE
_とメッセージを返します。このように、setopはシェルで使用できます。 setop inputfile --contains "value" # is element value contained in input? setop A.txt B.txt --equal C.txt # union of A and B equal to C? setop bigfile --subset smallfile # analogous --superset setop -i file1 file2 --is-empty # intersection of 1 and 2 empty (disjoint)?
また、実際には正規表現によって、入力ストリームを解析する方法を正確に説明することもできます。
setop input.txt --input-separator "[[:space:]-]"
_は、空白(つまり、_\v
_ _\t
_ _\n
_ _\r
_ _\f
_またはスペース)またはマイナス記号が要素間の区切り文字として解釈されることを意味します(デフォルトは改行です。つまり、入力ファイルのすべての行が1つの要素です)setop input.txt --input-element "[A-Za-z]+"
_は、要素がラテン文字で構成される単語のみであり、他のすべての文字は要素間の区切り文字と見なされることを意味しますさらに、
--count
_出力セットのすべての要素、--trim
_すべての入力要素(つまり、スペース、コンマなどの不要な前後の文字をすべて削除します)、--include-empty
_を介して有効であると見なし、--ignore-case
_、--output-separator
_を設定します(デフォルトは_\n
_です)、詳細については、_man setop
_または github.com/phisigma/setop を参照してください。
私は特定のツールを知りませんが、Pythonとそのセットクラスと演算子を使用して、それを行う小さなスクリプトを書くことができます。
たとえば:
Python> s1 = set(os.listdir("/bin"))
Python> s2 = set(os.listdir("/usr/bin"))
Python> s1 & s2
set(['awk',
'basename',
'chroot', ...
ファイルが一連の行として表示され、ファイルが並べ替えられている場合、 comm
があります。
ファイルが行の(マルチ)セットとして表示され、行がソートされていない場合、grep
は差と交差を実行できます(セットの差と交差を実現しますが、マルチセットのカウントは考慮しません)。 。 Unionはcat
です。
grep -xF -f small large >intersection
grep -vxF -f small large >difference
cat small large >union
私はPythonユーティリティを作成しました。これは、複数のファイルの行ごとの結合、交差、差、積を実行できます。これはSetOpと呼ばれ、PyPIで見つけることができます( こちら) )。構文は次のようになります:
$ setop -i file1 file2 file3 # intersection
$ setop -d file1 file2 file3 # difference
これを行うための小さなツールを書いたので、さまざまな場所でとても役に立ちました。 UIは洗練されておらず、非常に大きなファイルのパフォーマンス特性についてはわかりません(リスト全体をメモリに読み込むため)。プログラムは https://github.com/nibrahim/lines にあります。それはPythonです。 pip install lines
を使用して取得できます。
現在、2つのファイルのユニオン、インターセクション、差分、対称差分をサポートしています。入力ファイルの各行は、セットの要素として扱われます。
また、2つの追加操作があります。ファイル内の空白行を絞り出す方法の1つと2番目の方法(これは私にとって非常に便利です)は、ファイルを調べて、類似した文字列のセットに分割することです。一般的なパターンに一致しないファイルをリストから探すために、これが必要でした。
フィードバックをお待ちしています。
zsh
配列の場合(zsh
配列には、任意のバイトシーケンスを含めることができます。0でも可)。
(その要素が一意であることを保証するために_typeset -U array
_を実行できることにも注意してください)。
_if ((${array[(Ie)$element]})); then
echo '$element is in $array'
fi
_
(I
配列添え字フラグを使用して、配列内の_$element
_の最後の出現のインデックスを取得します(見つからない場合は0)。e
を削除します(e
xact)__$element
_をパターンとして使用)
_if ((n = ${(M)#array:#$element})); then
echo "\$element is found $n times in \$array'
fi
_
_${array:#pattern}
_は、kshの_${var#pattern}
_のバリエーションです削除パターンに一致する要素を削除するのではなく、パターンに一致する要素を削除します。 _(M)
_(for matched)は、意味を逆にして、一致した要素以外をすべて削除します(パターンとして使用するには、_$~element
_を使用します)。
_common=("${(@)set1:*set2}")
_
_${set1:*set2}
_は配列の交差を行いますが、空の要素を保持するには"${(@)...}"
構文が必要です。
_[[ ${(j: :)${(q)array1}} = ${(j: :)${(q)array2}} ]]
_
配列が同一(かつ同じ順序)かどうかをテストします。 q
パラメータ展開フラグは要素を引用符で囲み(a=(1 "2 3")
対b=("1 2" 3)
などの問題を回避するため)、_(j: :)
_はスペースを使用して要素を結合してから文字列比較。
順序に関係なく、これらの要素が同じであることを確認するには、o
フラグを使用して順序付けします。重複を削除するには、u
フラグ(一意)も参照してください。
_[[ ${(j: :)${(qo)array1}} = ${(j: :)${(qo)array2}} ]]
_
_n=$#array
_
_if ((${#array1:*array2} == ${#array2})); then
echo '$array2 is included in $array1'
fi
_
_union=("$array1[@]" "$array2[@]")
_
(上記の_typeset -U
_またはu
パラメータ展開フラグを参照して、重複の場合を考慮してください)。ここでも、空の文字列が可能な値の1つでない場合は、次のように簡略化できます。
_union=($array1 $array2)
_
_complement=("${(@)array1:|array2}")
_
_$array1
_にない_$array2
_の要素の場合。
_min=${${(o)array}[1]} max=${${(o)array}[-1]}
_
_min=${${(no)array}[1]} max=${${(no)array}[-1]}
_
複数ファイルのサンプルパターン(この場合は交差):
eval `Perl -le 'print "cat ",join(" | grep -xF -f- ", @ARGV)' t*`
展開する:
cat t1 | grep -xF -f- t2 | grep -xF -f- t3
テストファイル:
seq 0 20 | tee t1; seq 0 2 20 | tee t2; seq 0 3 20 | tee t3
出力:
0
6
12
18
ここでのベストアンサー: Setdown(専用ツール)
私は、cliからSet操作を実行するsetdownというプログラムを作成しました。
Makefileに書き込むのと同様の定義を書き込むことで、セット操作を実行できます。
someUnion: "file-1.txt" \/ "file-2.txt"
someIntersection: "file-1.txt" /\ "file-2.txt"
someDifference: someUnion - someIntersection
そのかなりクールで、あなたはそれをチェックする必要があります。個人的には、セット操作を実行するジョブ用に作成されていないアドホックコマンドを使用することはお勧めしません。多くのセット操作を実行する必要がある場合や、相互に依存するセット操作がある場合は、うまく機能しません。 。それだけでなく、setdownを使用すると、他の集合演算に依存する集合演算を記述できます。
とにかくすごくかっこいいので、是非チェックしてみてください。
ファイルシステムは、ファイル名(パスを含むファイル名全体)を一意のものとして扱います。
操作?
A /およびb /のファイルを空のディレクトリc /にコピーして、新しいユニオンセットを取得できます。
-e name
のようなファイルテストとループまたは検索を使用すると、2つ以上のディレクトリに存在するファイルをチェックして、共通部分または相違点を取得できます。