grepとファイルへの書き込みを高速化
Aug 18 2020
誰かの助けをいただければ幸いです。現在、2つのファイル(どちらも同じ形式)があり、どちらもそれぞれ200万行を超えています。以下のファイルの例:
ファイル1:
00000001 YYYY
00000002 NYNN
00000003 YNYN
...
...
ファイル2:
00000001 YYNY
00000002 NYNN
00000003 YNYN
...
...
したがって、各ファイルの最初の行が異なることに注意してください。ファイル3に出力します。
00000001 YYYY
上記のプロセスを実行するために、次のbashスクリプトがあります。
- ファイル2の最初の8文字をgrepします。
- grepのエコー/出力をファイル1の行と比較します。
- それらが異なる場合は、(ファイル1からの)行をファイル3に書き込みます。
サンプルコードを提供したかったのですが、覚えておいてください。これはその場で作成しただけですが、スクリプトと同じ概念です。現在、私は24時間勤務しており、200万人のうち24万人しかオンラインにいません。どうすればこれを効率的にスピードアップできますか?
input="file1"
while IFS= read -r line
do
LineFromFile1=$("${echo $line}") firstEightChars=$("${echo $line:0:8}")
if grep -q "$firstEightChars" file2; then $LineFoundInFile2="$(grep $firstEightCharst file2)"
if [[ $line == $LineFoundInFile2 ]]; then
:
else
echo $line >> file3 done < "$input"
回答
5 dawg Aug 18 2020 at 11:06
これは、Pythonスクリプトを使用すると非常に簡単になります。
Pythonには、2つのファイルを1行ずつ読み取って比較するために使用できるzip関数があります。
Bashスクリプトの例:
echo '00000001 YYYY
00000002 NYNN
00000003 YNYN' >file1
echo '00000001 YYNY
00000002 NYNN
00000003 YNYN' >file2
python3 -c '
with open("file1") as f_1, open("file2") as f_2:
for t in zip(f_1, f_2):
if t[0][8:-1] != t[1][8:-1]: print(t[0])'
プリント:
00000001 YYYY
ここでの利点(awk
たとえば、単純なスクリプトに対する)は、各ファイルの1行だけがアクティブメモリにあり、2行が比較されます。
ただし、Unixには、説明されている問題に対する他の解決策があります。貼り付けとawk
:を使用することもできます
paste file1 file2 | awk '$2!=$4 {print $1 OFS $2}'
または、最初の列の数値がインデックスとして機能している場合は、joinとawkを使用できます。
join file1 file2 | awk '$2!=$3 {print $1 OFS $2}'
または、各ファイルの列1がソートされている場合は、commコマンド(列1と列3を抑制)も機能します。
comm -1 -3 file1 file2
3つのUnix / Linuxコマンド/パイプはすべて次のものを生成します。
00000001 YYYY