「test1.csv」があり、そこには
200,400,600,800
100,300,500,700
50,25,125,310
そしてtest2.csvには
100,4,2,1,7
200,400,600,800
21,22,23,24,25
50,25,125,310
50,25,700,5
今
diff test2.csv test1.csv > result.csv
は異なる
diff test1.csv test2.csv > result.csv
どちらが正しい順序かは分かりませんが、別のものが欲しいです。上記のコマンドは両方とも次のような出力をします。
2 > 100,4,2,1,7
3 2,3c3,5
4 < 100,300,500,700
5 < 50,25,125,310
6 \ No newline at end of file
7 ---
8 > 21,22,23,24,25
9 > 50,25,125,310
差分のみを出力したいので、results.csvは次のようになります。
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
試してみましたがdiff -q
、diff -s
うまくいきませんでした。順序は重要ではありません。重要なのは、> や < や空白なしで、違いだけを確認したいということです。
grep -FvF
小さなファイルではうまくいきましたが、大きなファイルではうまくいきませんでした。
最初のファイルには 500 万行以上が含まれ、2 番目のファイルには 1300 行が含まれます。
したがって、results.csv は約 4,998,700 行になります。
私も試してみましたgrep -F -x -v -f
が、うまくいきませんでした。
答え1
次のような仕事に向いているようですcomm
:
$ comm -3 <(sort test1.csv) <(sort test2.csv)
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
次のように説明されていますman comm
:
-1 suppress column 1 (lines unique to FILE1)
-2 suppress column 2 (lines unique to FILE2)
-3 suppress column 3 (lines that appear in both files)
つまり、-3
ファイルの 1 つに固有の行のみが印刷されます。ただし、それらの行は、どのファイルで見つかったかに応じてインデントされます。タブを削除するには、次のようにします。
$ comm -3 <(sort test1.csv) <(sort test2.csv) | tr -d '\t'
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
この場合、ファイルを並べ替える必要はなく、上記の手順を次のように簡略化できます。
comm -3 test1.csv test2.csv | tr -d '\t' > difference.csv
答え2
プロセス置換grep
での使用:bash
$ cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv)
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
出力を次のように保存しますresults.csv
:
cat <(grep -vFf test2.csv test1.csv) <(grep -vFf test1.csv test2.csv) >results.csv
<()
それはbash
プロセス置換パターンgrep -vFf test2.csv test1.csv
のみに固有の行を見つけますtest1.csv
grep -vFf test1.csv test2.csv
のみに固有の行を見つけますtest2.csv
最後に結果をまとめると
cat
またはオリは提案したコマンドのグループ化も使用できます。
$ { grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv; }
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
または、両方が STDOUT に書き込まれるため、最終的に追加されるので、次々に実行します。
$ grep -vFf test2.csv test1.csv; grep -vFf test1.csv test2.csv
100,300,500,700
100,4,2,1,7
21,22,23,24,25
50,25,700,5
答え3
行の順序が関係ない場合は、awk
または を使用しますperl
。
awk '{seen[$0]++} END {for (i in seen) {if (seen[i] == 1) {print i}}}' 1.csv 2.csv
grep
共通行を取得してフィルタリングするには、次を使用します。
grep -hxvFf <(grep -Fxf 1.csv 2.csv) 1.csv 2.csv
内部 grep は共通行を取得し、外部 grep はこれらの共通行に一致しない行を検索します。
答え4
順序を維持する必要がないので、次のようにします。
sort test1.csv test2.csv | uniq -u
sort test1.csv test2.csv
: マージとソートを行いtest1.csv
、test2.csv
uniq -u
: 重複のない行のみを出力します