Grep'i ve dosyaya yazmayı hızlandırın
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:
- 2. dosya için ilk SEKİZ karakteri grep.
- Grep'in eko / çıktısını dosya 1'deki satırla karşılaştırıyorum.
- 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
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