นี่คือสิ่งที่ awk ถูกออกแบบมาสำหรับ:
$ awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0' file2 file1
abc|123|BNY|apple|
cab|234|cyx|orange|
คำอธิบาย
-F'|'
: |
ชุดคั่นฟิลด์
NR==FNR
: NR คือหมายเลขบรรทัดอินพุตปัจจุบันและ FNR หมายเลขบรรทัดของไฟล์ปัจจุบัน ทั้งสองจะเท่ากันในขณะที่กำลังอ่านไฟล์ที่ 1
c[$1$2]++; next
: ถ้านี่คือไฟล์ที่ 1 ให้บันทึกสองฟิลด์แรกในc
อาร์เรย์ จากนั้นข้ามไปยังบรรทัดถัดไปเพื่อให้สิ่งนี้ใช้ได้กับไฟล์ที่ 1 เท่านั้น
c[$1$2]>0
: บล็อกอื่นจะถูกดำเนินการหากไฟล์นี้เป็นไฟล์ที่สองดังนั้นเราจะตรวจสอบว่าฟิลด์ 1 และ 2 ของไฟล์นี้ถูกเห็นแล้วหรือไม่ ( c[$1$2]>0
) และหากเป็นเช่นนั้นเราจะพิมพ์บรรทัดนั้น ในawk
การดำเนินการเริ่มต้นคือการพิมพ์บรรทัดดังนั้นหากc[$1$2]>0
เป็นจริงสายจะถูกพิมพ์
อีกทางเลือกหนึ่งเนื่องจากคุณติดแท็กด้วย Perl:
perl -e 'open(A, "file2"); while(<A>){/.+?\|[^|]+/ && $k{$&}++};
while(<>){/.+?\|[^|]+/ && do{print if defined($k{$&})}}' file1
คำอธิบาย
บรรทัดแรกจะเปิดfile2
ขึ้นอ่านทุกอย่างจนถึงอันดับ 2 |
( .+?\|[^|]+
) และบันทึกไว้ ( $&
เป็นผลลัพธ์ของผู้ดำเนินการจับคู่ล่าสุด) ใน%k
แฮช
บรรทัดที่สองประมวลผล file1 ใช้ regex เดียวกันเพื่อแยกคอลัมน์แรกที่สองและพิมพ์บรรทัดหากคอลัมน์เหล่านั้นถูกกำหนดใน%k
แฮช
ทั้งสองวิธีข้างต้นจะต้องเก็บ 2 คอลัมน์แรกของ file2 ในหน่วยความจำ นั่นไม่ควรเป็นปัญหาหากคุณมีเพียงไม่กี่แสนบรรทัด แต่ถ้าเป็นเช่นนั้นคุณสามารถทำอะไรบางอย่างได้
cut -d'|' -f 1,2 file2 | while read pat; do grep "^$pat" file1; done
แต่นั่นจะช้าลง