เร่งความเร็ว grep และเขียนลงไฟล์

Aug 18 2020

ฉันจะขอบคุณทุกคนที่ช่วยเหลือ ตอนนี้ฉันมี 2 ไฟล์ (ทั้งสองรูปแบบเหมือนกัน) และทั้งคู่มีมากกว่า 2 ล้านบรรทัดในแต่ละไฟล์ ตัวอย่างไฟล์ด้านล่าง:

ไฟล์ 1:

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

ไฟล์ 2:

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

สังเกตว่าบรรทัดแรกในแต่ละไฟล์แตกต่างกันดังนั้นฉันจะพิมพ์เป็นไฟล์ 3:

00000001 YYYY

ในการทำกระบวนการข้างต้นฉันมีสคริปต์ทุบตีเพื่อ:

  1. grep อักขระแปดตัวแรกสำหรับไฟล์ 2
  2. ฉันเปรียบเทียบ echo / output ของ grep กับบรรทัดในไฟล์ 1
  3. หากแตกต่างกันให้เขียนบรรทัด (จากไฟล์ 1) ไปยังไฟล์ 3

ฉันต้องการให้โค้ดตัวอย่าง แต่โปรดทราบว่าฉันเพิ่งสร้างสิ่งนี้ขึ้นมาทันที แต่เป็นแนวคิดเดียวกับสคริปต์ของฉัน ขณะนี้ฉันอยู่ในสาย 24 ชั่วโมงและมีเพียง 240,000 บรรทัดจาก 2 ล้านคน ฉันจะเร่งความเร็วอย่างมีประสิทธิภาพได้อย่างไร

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 มีฟังก์ชัน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ตัวอย่างเช่นสคริปต์ทั่วไป) มีเพียงบรรทัดเดียวของแต่ละไฟล์เท่านั้นที่อยู่ในหน่วยความจำที่ใช้งานอยู่ - เปรียบเทียบสองบรรทัด

อย่างไรก็ตาม Unix มีวิธีแก้ไขปัญหาอื่น ๆ ที่อธิบายไว้ คุณยังสามารถใช้วางและawk:

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

หรือถ้าตัวเลขในคอลัมน์แรกทำหน้าที่เป็นดัชนีคุณสามารถใช้joinและ awk:

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

หรือคำสั่งcomm (ระงับ col 1 และ col 3) หากเรียงคอลัมน์ 1 ในแต่ละไฟล์ก็จะใช้ได้เช่นกัน:

comm -1 -3 file1 file2

ทั้งสามคำสั่ง Unix / Linux / ท่อผลิต:

00000001 YYYY