わかりました。私の Linux ボックスには、テキスト ファイルで 2 つの関連リストがあります。
/tmp/oldList
/tmp/newList
これらのリストを比較して、追加された行と削除された行を確認する必要があります。次に、これらの行をループして、追加または削除されたかどうかに基づいてアクションを実行する必要があります。
これを bash で行うにはどうすればよいですか?
コマンドを使用しcomm(1)
て、2 つのファイルを比較します。どちらもソートする必要があります。大きい場合は事前にソートするか、bashプロセス置換を使用してインラインでソートできます。
comm
flags の組み合わせを取り、-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))
新しい行についても同様です。
diff コマンドは、比較を行います。
例えば、
$ diff /tmp/oldList /tmp/newList
詳細については、上記のマニュアル ページのリンクを参照してください。これにより、問題の最初の部分が処理されます。
スクリプトに可読性が必要な場合は、Ruby の使用を検討してください。
古いファイルの行のみを取得するには:
ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')"
新しいファイルの行のみを取得するには:
ruby -e "puts File.readlines('/tmp/newList') - File.readlines('/tmp/oldList')"
これを while read ループにフィードして、各行を処理できます。
while read old ; do
...do stuff with $old
done < ruby -e "puts File.readlines('/tmp/oldList') - File.readlines('/tmp/newList')"
これは古いですが、完全を期すために、非常に大きなセットがある場合、最速の解決策は、次のように diff を使用してスクリプトを生成し、それを source することです。
#!/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 を使用できます。差分マニュアルページを確認してください。
やってみましたdiff
$ diff /tmp/oldList /tmp/newList
$ man diff