วิธีพิมพ์สองคอลัมน์สุดท้ายโดยใช้ awk


106

ทั้งหมดที่ฉันต้องการคือสองคอลัมน์สุดท้ายที่พิมพ์


6
ไม่แน่ใจว่าทำไมถึงมี 87 upvotes แต่อย่างน้อยก็สามารถปรับปรุงได้อย่างแน่นอนด้วยตัวอย่าง
Arj

อาจเป็นเพราะคำถามนั้นง่ายมากโดยธรรมชาติและเข้าใจได้ง่ายโดยไม่มีตัวอย่างซึ่งหาได้ยาก แต่ในกรณีนี้ดูเหมือนจะได้ผล ปัญหาที่นี่ไม่ใช่การขาดข้อมูลที่ฉันคิด แต่มีมากกว่านั้นที่แสดงให้เห็นว่าขาดการค้นคว้าอิสระ
DryLabRebel

คำถามนี้ซ้ำกับคำถามนี้ด้วย
DryLabRebel

สิ่งนี้ตอบคำถามของคุณหรือไม่? พิมพ์คอลัมน์ / ฟิลด์สุดท้ายที่สองใน awk
DryLabRebel

คำตอบ:


194

คุณสามารถใช้ตัวแปรNFที่กำหนดเป็นจำนวนฟิลด์ทั้งหมดในบันทึกอินพุต:

awk '{print $(NF-1),"\t",$NF}' file

ถือว่าคุณมีอย่างน้อย 2 ช่อง


1
คุณต้องใช้ลูกน้ำ - เนื่องจากวันนี้เราจู้จี้จุกจิก: ช่องว่างที่เชื่อมต่อกับฟิลด์คอมมาจะแยกฟิลด์ในคำสั่งการพิมพ์ ที่จะรวมสองช่อง
jim mcnamara

18
ตอนนี้คุณกำลังพิมพ์ "field-OFS-tab-OFS-field" มันควรจะเป็นawk '{print $(NF-1) "\t" $NF}' fileหรือหรือawk '{print $(NF-1), $NF}' file awk 'BEGIN{OFS="\t"} {print $(NF-1), $NF}' file
หยุดชั่วคราวจนกว่าจะมีประกาศอีกครั้ง

เพียงเพื่อเพิ่มความคิดเห็นก่อนหน้านี้ปัญหาในการใช้'{print $x,"\t",$y}'คือ awk ตีความตัวแปรที่คั่นด้วยเครื่องหมายจุลภาคแต่ละตัวว่าเป็นฟิลด์ของตัวเองดังนั้นผลลัพธ์จะเป็นจริงfield1<space><tab><space>field2(เพราะจะใช้ตัวคั่นช่องว่างสีขาวตามค่าเริ่มต้น) ซึ่งตรงข้ามกับfield1<tab>field2ซึ่งอาจเป็นอะไร คุณกำลังคาดหวัง การใช้ตัวคั่นฟิลด์เอาต์พุต (OFS) เป็นสิ่งที่คุณต้องการเกือบตลอดเวลา
DryLabRebel

13
awk '{print $NF-1, $NF}'  inputfile

หมายเหตุ: จะใช้ได้เฉพาะเมื่อมีอย่างน้อยสองคอลัมน์ ในบันทึกที่มีคอลัมน์เดียวคุณจะได้รับของปลอม"-1 column1"


3
ลองดู มันทำงาน Solaris 9 awk & nawk ทางเลือกคือ $ (NF-1)
jim mcnamara

1
@coaddict - ฉันเดาว่าคุณไม่ได้ทำงานกับการใช้งาน awk ที่แตกต่างกัน พฤติกรรมเก่า ๆ ได้รับ (อาจผิดพลาด) นำไปข้างหน้า ฉันไม่มีปากที่จะทดสอบ - ซึ่งอาจเป็นสิ่งที่คุณอ้างถึง ฉันจึงไม่รู้แน่ชัดว่าทำไมความคิดเห็นของคุณถึงมีความผิดปกติ Linux awk นอกกรอบมักจะเป็น gawk ฉันจะทดสอบและโพสต์กลับ ในขณะเดียวกันลอง Soalris หรือ HPUX หรือ DGX หรืออะไรก็ได้เพื่อดูว่าฉันหมายถึงอะไรโดย awk เก่า
jim mcnamara

6
echo 1 2 3 | awk ...คุณอาจได้หลอกให้คิดว่ามันทำงานเพราะคุณพยายาม $NF-1อยู่($NF) - 1ในทุกawkการนำไปใช้งาน
Stephane Chazelas

ซอร์สโค้ด "One True Awk" มีความขัดแย้งในyaccไวยากรณ์มากกว่า 40 ข้อซึ่งเป็นเรื่องที่น่าขันเมื่อเทียบกับสิ่งที่ A ย่อมาจาก awk awk เวอร์ชันต่างๆแยกวิเคราะห์ต่างกันหรือไม่ เซอร์ไพรส์ครั้งใหญ่!
Kaz

1
@THESorcerer ลองใช้echo '5 4 3 2 1' | awk '{print $NF-1,$NF; print $(NF-1), $NF}'- หรืออินพุตอื่นใดฟิลด์สุดท้ายที่ 2 ไม่น้อยกว่าฟิลด์สุดท้าย
glenn jackman

6

นารา @ Jim: ลองใช้วงเล็บประมาณNFคือ $(NF-1)และ$(NF)แทน$NF-1และ$NF(ทำงานบน Mac OS X 10.6.8 สำหรับ FreeBSD awkและgawk)

echo '
1 2
2 3
one
one two three
' | gawk '{if (NF >= 2) print $(NF-1), $(NF);}'

# output:
# 1 2
# 2 3
# two three

เราได้พิจารณา () ก่อนหน้านี้แล้ว ฉันคิดว่าเรากำลังคุยกันว่าพฤติกรรมเดิม ๆ ของ awk มาจากไหน
jim mcnamara

+1 สำหรับคำตอบอย่างชัดเจนด้วย$(NF-1)- ซึ่งอย่างน้อยที่สุดเป็นแบบพกพามากกว่า$NF-1; มันคลุมเครือน้อยกว่าแน่นอน $(NF)เป็นเรื่องที่มากเกินไป - ก็$NFจะทำ การป้องกันบรรทัดที่มีน้อยกว่า 2 คอลัมน์ก็คุ้มค่าเช่นกันเช่นเดียวกับบรรทัดหนึ่งคอลัมน์คุณจะได้รับค่าคอลัมน์แรกสองครั้งและด้วยคอลัมน์ศูนย์ - กล่าวคือบรรทัดว่างคำสั่ง awk จะล้มเหลวทั้งหมดเนื่องจากความพยายาม เพื่อเข้าถึงฟิลด์ที่มีดัชนี -1
mklement0

1

การใช้ gawk แสดงปัญหา:

 gawk '{ print $NF-1, $NF}' filename
1 2
2 3
-1 one
-1 three
# cat filename
1 2
2 3
one
one two three

ฉันใส่ gawk กับ Solaris 10 M4000: ดังนั้น gawk คือ cuplrit ในปัญหา $ NF-1 เทียบกับ $ (NF-1) คำถามต่อไป POSIX พูดว่าอะไร? ต่อ:

http://www.opengroup.org/onlinepubs/009695399/utilities/awk.html

ไม่มีทิศทางไปทางใดทางหนึ่ง ไม่ดี. gawk หมายถึงการลบ awks อื่น ๆ หมายถึงหมายเลขฟิลด์หรือการลบ อืม.


1
2 บรรทัดแรกของไฟล์อินพุตตัวอย่างของคุณไม่เป็นประโยชน์ในการสร้างเอาต์พุตเดียวกันกับพฤติกรรมอย่างใดอย่างหนึ่ง คุณช่วยยืนยันอีกครั้งได้ไหมว่า Solaris awk ไม่ทำตัวเหมือน gawk ในกรณีนี้?
mklement0

สำหรับลิงก์ของคุณไปยังข้อมูลจำเพาะ awk: อาร์กิวเมนต์สรุปสำหรับการใช้งาน$(NF-1)คือตัวอย่างสองตัวอย่างของการคำนวณดัชนีฟิลด์ในข้อมูลจำเพาะทั้งสองใช้รูปแบบนั้น: $(NF-1)และ$(NF+2). จากนั้นก็มีส่วน "การแสดงออกใน awk" ซึ่งรายการ$exprที่มีความสำคัญ [มาก] expr - exprสูงกว่า ตั้งแต่NFคือการแสดงออกของตัวเองควรที่จะประเมิน$NF-1 ($NF)-1แม้แต่ IF ก็ยังมีการใช้งาน awk ที่ประเมินได้$NF-1ว่า$(NF-1)บทเรียนที่ได้เรียนรู้ที่นี่คือการใช้$(NF-1)เป็นตัวเลือกที่ปลอดภัยและพกพาได้
mklement0

0

ลองกับสิ่งนี้

$ cat /tmp/topfs.txt
/dev/sda2      xfs        32G   10G   22G  32% /

awk print last column
$ cat /tmp/topfs.txt | awk '{print $NF}'

awk print before last column
$ cat /tmp/topfs.txt | awk '{print $(NF-1)}'
32%

awk - print last two columns
$ cat /tmp/topfs.txt | awk '{print $(NF-1), $NF}'
32% /

0

โปรดลองใช้สิ่งนี้เพื่อพิจารณาสถานการณ์ที่เป็นไปได้ทั้งหมด:

awk '{print $(NF-1)"\t"$NF}'  file

หรือ

awk 'BEGIN{OFS="\t"}' file

หรือ

awk '{print $(NF-1), $NF} {print $(NF-1), $NF}' file
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.