การใช้ตัวคั่นหลายตัวใน awk


202

ฉันมีไฟล์ที่มีบรรทัดต่อไปนี้:

/logs/tc0001/tomcat/tomcat7.1/conf/catalina.properties:app.env.server.name = demo.example.com
/logs/tc0001/tomcat/tomcat7.2/conf/catalina.properties:app.env.server.name = quest.example.com
/logs/tc0001/tomcat/tomcat7.5/conf/catalina.properties:app.env.server.name = www.example.com

ในผลลัพธ์ข้างต้นฉันต้องการแยก 3 ฟิลด์ (หมายเลข 2, 4 และอันสุดท้าย*.example.com) ฉันได้รับผลลัพธ์ต่อไปนี้:

cat file | awk -F'/' '{print $3 "\t" $5}'
tc0001   tomcat7.1
tc0001   tomcat7.2
tc0001   tomcat7.5

ฉันจะแยกฟิลด์สุดท้ายด้วยชื่อโดเมนที่อยู่หลังได้'='อย่างไร ฉันจะใช้multiple delimiterเพื่อแยกฟิลด์ได้อย่างไร


2
เพื่อตอบคำถามของฉันซึ่งเหมือนกัน แต่แตกต่างกันawkคือกลืนฟิลด์เมื่อมันว่างซึ่งทำให้เกิดหมายเลขฟิลด์ ฉันเปลี่ยน-F " "เป็น-F "[ ]"และawkไม่กลืนฟิลด์ว่างอีกต่อไป
อดัม

คำตอบ:


324

ตัวคั่นอาจเป็นนิพจน์ทั่วไป

awk -F'[/=]' '{print $3 "\t" $5 "\t" $8}' file

ผลิต:

tc0001   tomcat7.1    demo.example.com  
tc0001   tomcat7.2    quest.example.com  
tc0001   tomcat7.5    www.example.com

42
แน่นอนว่ากระบวนการไม่จำเป็นต้อง:cat awk '...' fileนอกจากนี้ยังเป็นเรื่องที่ดีที่จะใช้ตัวคั่นฟิลด์เอาต์พุต:awk -F'[/=]' -v OFS="\t" '{print $3, $5, $8}'
glenn jackman

17
ตัวคั่น Awk อาจเป็นนิพจน์ปกติ ... นี่ทำให้วันของฉัน!
das.cyklone

4
@ das.cyklone: awk ยังสามารถมีแยกหลายกับ|: อดีต: awk -F 'this|that|[=/]' '......' (ประโยชน์ที่จะมีคำ / สายแยกสิ่ง) (หมายเหตุว่านี้ช่วยให้ช่องว่างใน fiels ระหว่าง 2 คั่นเพิ่มยัง. |[ \t]+จะมีประโยชน์ แต่สามารถทำสิ่งที่ หากิน ... เนื่องจากมักจะมีช่องว่างก่อนและหลัง 'นี่' จะทำให้มี 2 ฟิลด์ว่างปรากฏระหว่างพื้นที่และ 'this')
Olivier Dulac

ฉันได้ลองใน distros ที่แตกต่างกัน 2 และฉันได้รับพฤติกรรมเดียวกัน: ฉันต้องการรับพอร์ตจาก netstat -ntpl "netstat -ntpl | sed 's /: / / /' | awk '{print $ 5}'" ทำงาน แต่ สามารถทำได้โดยไม่ต้องใช้ doulbe piping งานนี้ แต่ฉันไม่ได้คาดหวังว่าข้อมูลในฟิลด์ที่ 17: "netstat -ntpl | awk -F" |: "'{พิมพ์ $ 17}'"
louigi600

2
ใช่ ... สิ่งนี้ทำให้ฉันได้ในสิ่งที่ฉันต้องการ: awk -F "[:] +" '/ \ / postmaster * $ / {พิมพ์ $ 5}'
louigi600

44

ข่าวดี! awkตัวคั่นฟิลด์สามารถเป็นนิพจน์ทั่วไป คุณเพียงแค่ต้องใช้-F"<separator1>|<separator2>|...":

awk -F"/|=" -vOFS='\t' '{print $3, $5, $NF}' file

ผลตอบแทน:

tc0001  tomcat7.1  demo.example.com
tc0001  tomcat7.2  quest.example.com
tc0001  tomcat7.5  www.example.com

ที่นี่:

  • -F"/|="ชุดแยกช่องใส่อย่างใดอย่างหนึ่งหรือ/ =จากนั้นจะตั้งค่าตัวคั่นฟิลด์เอาต์พุตเป็นแท็บ

  • -vOFS='\t'ใช้-vค่าสถานะสำหรับการตั้งค่าตัวแปร OFSเป็นตัวแปรเริ่มต้นสำหรับตัวคั่นฟิลด์เอาต์พุตและตั้งค่าเป็นอักขระแท็บ ธงเป็นสิ่งจำเป็นเพราะมีในตัวไม่มี OFS -Fเช่น

  • {print $3, $5, $NF} พิมพ์ฟิลด์ที่ 3, 5 และสุดท้ายตามตัวคั่นฟิลด์อินพุต


ดูตัวอย่างอื่น:

$ cat file
hello#how_are_you
i#am_very#well_thank#you

ไฟล์นี้มีสองช่องแยกและ# _ถ้าเราต้องการพิมพ์เขตข้อมูลที่สองโดยไม่คำนึงถึงตัวคั่นที่เป็นหนึ่งหรืออื่น ๆ ให้ทั้งสองเป็นตัวคั่น!

$ awk -F"#|_" '{print $2}' file
how
am

ตำแหน่งของไฟล์มีดังนี้:

hello#how_are_you           i#am_very#well_thank#you
^^^^^ ^^^ ^^^ ^^^           ^ ^^ ^^^^ ^^^^ ^^^^^ ^^^
  1    2   3   4            1  2   3    4    5    6

1
ขอบคุณ @BUFU สำหรับการแก้ไขของคุณ ฉันลบการอ้างอิง OFS เพื่อมุ่งเน้นที่ส่วน FS แต่ก็เป็นการดีเช่นกัน ไชโย!
fedorqui 'ดังนั้นหยุดทำร้าย'

5

หากช่องว่างของคุณสอดคล้องกันคุณสามารถใช้สิ่งนั้นเป็นตัวคั่นได้เช่นกันแทนที่จะใส่\tโดยตรงคุณสามารถตั้งค่าตัวแยกเอาต์พุตและมันจะถูกรวมโดยอัตโนมัติ:

< file awk -v OFS='\t' -v FS='[/ ]' '{print $3, $5, $NF}'

3

สำหรับตัวคั่นฟิลด์ของตัวเลขใด ๆ2ผ่าน5หรือจดหมายaหรือ#ช่องว่างโดยที่อักขระการแยกต้องทำซ้ำอย่างน้อย 2 ครั้งและไม่เกิน 6 ครั้งตัวอย่างเช่น:

awk -F'[2-5a# ]{2,6}' ...

ฉันแน่ใจว่ารูปแบบนี้มีอยู่โดยใช้ () และพารามิเตอร์


3

Perl หนึ่งซับ:

perl -F'/[\/=]/' -lane 'print "$F[2]\t$F[4]\t$F[7]"' file

ใช้ตัวเลือกบรรทัดคำสั่งเหล่านี้:

  • -nวนรอบทุกบรรทัดของไฟล์อินพุตใส่บรรทัดใน$_ตัวแปรอย่าพิมพ์ทุกบรรทัดโดยอัตโนมัติ

  • -l ลบบรรทัดใหม่ก่อนการประมวลผลและเพิ่มพวกเขากลับมาในภายหลัง

  • -aโหมด autosplit - perl จะแยกบรรทัดอินพุตให้เป็น@Fอาร์เรย์โดยอัตโนมัติ ค่าเริ่มต้นที่จะแยกในช่องว่าง

  • -Fตัวดัดแปลงอัตโนมัติในตัวอย่างนี้แยกอย่างใดอย่างหนึ่ง/หรือ=

  • -e รันรหัส Perl

Perl มีความเกี่ยวข้องอย่างใกล้ชิดกับ awk อย่างไรก็ตาม@Fอาร์เรย์ autosplit เริ่มต้นที่ดัชนี$F[0]ในขณะที่ฟิลด์ awk เริ่มต้นด้วย $ 1


2

อีกคนหนึ่งคือการใช้ตัวเลือก -F แต่ผ่านมัน regex ()พิมพ์ข้อความระหว่างวงเล็บซ้ายและหรือขวา

เนื้อหาของไฟล์:

528(smbw)
529(smbt)
530(smbn)
10115(smbs)

คำสั่ง:

awk -F"[()]" '{print $2}' filename

ผลลัพธ์:

smbw
smbt
smbn
smbs

การใช้ awk เพื่อพิมพ์ข้อความระหว่าง[]:

ใช้awk -F'[][]' แต่ awk -F'[[]]'จะไม่ทำงาน

http://stanlo45.blogspot.com/2020/06/awk-multiple-field-separators.html


คำตอบของคุณเกิดขึ้นในคิวการลบเพราะ 9 ครั้งจาก 10 ครั้งผู้ใช้ที่มี 1 ชื่อเสียงที่เชื่อมโยงไปยังบล็อกของตนเองมักเป็นสแปม แต่คุณเป็นข้อยกเว้นของกฎ เนื้อหาในช่วง 10 ปีที่ผ่านมามีเหมืองทองคำหวังว่าคุณจะมีแผนที่จะทำให้เป็นอมตะ
Eric Leschinski

0

ฉันเห็นคำตอบที่สมบูรณ์แบบมากมายอยู่บนกระดาน แต่ยังต้องการอัปโหลดโค้ดของฉันด้วย

awk -F"/" '{print $3 " " $5 " " $7}' sam | sed 's/ cat.* =//g'


2
print $3 " " $5 " " $7print $3, $5, $7สามารถพิมพ์ได้เช่นเดียวกับ นอกจากนี้ฉันไม่เห็นประโยชน์ของการใช้ awk และจากนั้นไปที่ท่อเพื่อ sed โดยทั่วไป awk สามารถพอเพียงและคำตอบอื่น ๆ แสดงให้เห็นว่า
fedorqui 'ดังนั้นหยุดการทำร้าย'
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.