web-dev-qa-db-ja.com

Bashを使用した2つのリストの違い

わかりました、私のLinuxボックスにテキストファイルで2つの関連リストがあります。

 /tmp/oldList
 /tmp/newList

追加された行と削除された行を確認するには、これらのリストを比較する必要があります。次に、これらの行をループして、それらが追加されたか削除されたかに基づいて、それらに対してアクションを実行する必要があります。

Bashでこれを行うにはどうすればよいですか?

31
exvance

comm(1)コマンドを使用して、2つのファイルを比較します。どちらもソートする必要があります。それらが大きい場合は事前に行うことができます。または、bash プロセス置換を使用してインラインで行うこともできます。

commはフラグの組み合わせをとることができます-1-2および-3行を抑制するファイルを示します(ファイル1に固有、ファイル2に固有、または両方に共通)。

古いファイルのみの行を取得するには:

comm -23 <(sort /tmp/oldList) <(sort /tmp/newList)

新しいファイルでのみ行を取得するには:

comm -13 <(sort /tmp/oldList) <(sort /tmp/newList)

これをwhile readループして各行を処理します。

while read old ; do
    ...do stuff with $old
done < <(comm -23 <(sort /tmp/oldList) <(sort /tmp/newList))

そして、新しいラインについても同様です。

62
camh

diffコマンド が比較を行います。

例えば。、

$ diff /tmp/oldList /tmp/newList

詳細については、上記のmanページのリンクを参照してください。これにより、問題の最初の部分が処理されます。

5
Levon

スクリプトに読みやすさが必要な場合は、Rubyの使用を検討してください。

古いファイルのみの行を取得するには:

Ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')"

新しいファイルでのみ行を取得するには:

Ruby -e "puts File.readlines('/tmp/newList') - File.readlines('/tmp/oldList')"

これをwhile読み取りループにフィードして、各行を処理できます。

while read old ; do
  ...do stuff with $old
done < Ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')"
4
Nowaker

これは古いですが、完全にするために、本当に大きなセットがある場合は、次のようにdiffを使用してスクリプトを生成し、それをソースにするのが最も速いと言うべきです。

#!/bin/bash

line_added() {
   # code to be run for all lines added
   # $* is the line 
}

line_removed() {
   # code to be run for all lines removed
   # $* is the line 
}

line_same() {
   # code to be run for all lines at are the same
   # $* is the line 
}

cat /tmp/oldList | sort >/tmp/oldList.sorted
cat /tmp/newList | sort >/tmp/newList.sorted

diff >/tmp/diff_script.sh \
    --new-line-format="line_added %L" \
    --old-line-format="line_removed %L" \
    --unchanged-line-format="line_same %L" \
    /tmp/oldList.sorted /tmp/newList.sorted

source /tmp/diff_script.sh

変更された行は、削除および追加されたものとして表示されます。これが気に入らない場合は、-changed-group-formatを使用できます。差分のマニュアルページを確認してください。

1
Costa Tsaousis

diffを試しましたか

$ diff /tmp/oldList /tmp/newList

$ man diff
0
ssedano

私は通常使用します:

diff /tmp/oldList /tmp/newList | grep -v "Common subdirectories"

grep -vオプションは一致を反転します:

-v、--invert-match選択された行は、指定されたパターンのいずれとも一致しないものです。

したがって、この場合はdiffの結果を受け取り、一般的な結果は省略します。

0
Nathan