Mempercepat grep dan menulis ke file

Aug 18 2020

Saya sangat menghargai bantuan siapa pun. Saat ini, saya memiliki 2 file (keduanya diformat sama) dan masing-masing memiliki lebih dari 2 juta baris. Contoh file di bawah ini:

file 1:

00000001 YYYY
00000002 NYNN
00000003 YNYN
...
...

file 2:

00000001 YYNY
00000002 NYNN
00000003 YNYN
...
...

Jadi perhatikan baris pertama di setiap file berbeda jadi saya akan mencetak ke file 3:

00000001 YYYY

Untuk melakukan proses di atas, saya memiliki skrip bash untuk:

  1. grep DELAPAN karakter pertama untuk file 2.
  2. Saya membandingkan echo / output grep dengan baris di file 1.
  3. JIKA mereka berbeda, tulis baris (dari file 1) ke file 3.

Saya ingin memberikan kode sampel tetapi perlu diingat, saya baru saja membuat ini dengan cepat TAPI konsepnya sama dengan skrip saya. Saat ini, saya 24 jam masuk dan hanya on line 240k dari 2 juta. Bagaimana saya bisa mempercepatnya dengan cara yang efisien?

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"

Jawaban

5 dawg Aug 18 2020 at 11:06

Ini akan sangat sederhana dengan skrip Python.

Python memiliki fungsi zip yang dapat digunakan untuk membaca dan membandingkan dua file baris demi baris.

Contoh skrip 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])'

Cetakan:

00000001 YYYY

Keuntungannya di sini (dibandingkan awkskrip sederhana misalnya) hanya satu baris dari setiap file dalam memori aktif - dua baris dibandingkan.

Namun, Unix memiliki solusi lain untuk masalah yang dijelaskan. Anda juga dapat menggunakan pasta dan awk:

paste file1 file2 | awk '$2!=$4 {print $1 OFS $2}'

Atau jika angka di kolom pertama berfungsi sebagai indeks, Anda dapat menggunakan join dan awk:

join file1 file2 | awk '$2!=$3 {print $1 OFS $2}'

Atau perintah comm (menekan col 1 dan col 3) jika kolom 1 di setiap file diurutkan akan berfungsi juga:

comm -1 -3 file1 file2

Ketiga perintah / pipa Unix / Linux menghasilkan:

00000001 YYYY