Grep'i ve dosyaya yazmayı hızlandırın

Aug 18 2020

Herhangi birinin yardımına minnettar olurum. Şu anda 2 dosyam var (ikisi de aynı şekilde biçimlendirilmiş) ve her ikisinde de 2 milyondan fazla satır var. Aşağıdaki dosya örnekleri:

dosya 1:

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

dosya 2:

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

Bu yüzden her dosyadaki ilk satırın farklı olduğuna dikkat edin, bu yüzden 3. dosyaya yazdırırım:

00000001 YYYY

Yukarıdaki işlemi yapmak için, bir bash betiğim var:

  1. 2. dosya için ilk SEKİZ karakteri grep.
  2. Grep'in eko / çıktısını dosya 1'deki satırla karşılaştırıyorum.
  3. Farklı iseler, satırı (1. dosyadan) 3. dosyaya yazın.

Örnek kod sağlamak istedim, ancak aklınızda bulundurun, bunu anında uydurdum AMA betiğimle aynı konsept. Şu anda, 24 saat içerideyim ve sadece 2 milyonun 240k hattındayım. Bunu verimli bir şekilde nasıl hızlandırabilirim?

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"

Yanıtlar

5 dawg Aug 18 2020 at 11:06

Bir Python betiği ile bu çok basit olurdu .

Python, iki dosyayı satır satır okumak ve karşılaştırmak için kullanılabilen zip işlevine sahiptir.

Örnek Bash komut dosyası:

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

Baskılar:

00000001 YYYY

Buradaki avantaj ( awkörneğin basit bir komut dosyasına göre) her dosyanın yalnızca bir satırı aktif bellekte - iki satırın karşılaştırılması.

Bununla birlikte, Unix'in açıklanan soruna başka çözümleri vardır. Ayrıca yapıştır ve şunları da kullanabilirsiniz awk:

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

Veya ilk sütundaki sayılar bir dizin görevi görüyorsa, join ve awk'yi kullanabilirsiniz :

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

Veya her dosyadaki sütun 1 sıralanırsa comm komutu (sütun 1 ve sütun 3'ü gizleyerek) da çalışacaktır:

comm -1 -3 file1 file2

Üç Unix / Linux komutu / kanalının tümü şunları üretir:

00000001 YYYY