สามารถใช้ awk แทนได้หรือไม่


17

ฉันต้องการรับหมายเลขratingเป็นผลลัพธ์จากสิ่งนี้

# nc localhost 9571 
language:
language:en_ZA.UTF-8
language:en_ZW.UTF-8
session-with-name:Ubuntu Classic (No effects):gnome-session --session=2d-gnome
session-with-name:Ubuntu (Safe Mode):gnome-session -f --session=2d-gnome
session-with-name:Ubuntu Classic:gnome-session --session=classic-gnome
xsession:/etc/X11/Xsession
rating:94

ฉันสามารถทำสิ่งนี้ได้

# nc localhost 9571 | grep rating | cut -d: -f2
94

แต่สามารถawkใช้แทนโซลูชันที่ง่ายกว่าได้ไหม


คำถามนี้ดูเหมือนจะไม่เป็นหัวข้อเพราะเป็นเรื่องเกี่ยวกับการเขียนโปรแกรมในอินเทอร์เฟซ Awk และมีความเกี่ยวข้องมากขึ้นใน StackOverflow.com
Magellan

คำตอบ:


32
$ nc localhost 9571 | awk -F: '/rating/ { print $2 }'

7
สามารถให้ผลลัพธ์ที่ไม่ถูกต้องหากค่าฟิลด์หรือชื่อใดมีสตริง "rating" นั่นคือหนึ่งในชื่อเซสชันมีคำว่า "rating" อยู่ ดีกว่า:awk -F: '$1 == "rating" {print $2}'
อิงมาร์ Hupp

3
หรืออาจจะawk -F: '/^rating:/ { print $2 }'?
CVn

ฉันรู้ว่า แต่ฉันแปลงตามคำสั่งของ OP
quanta

@IngmarHupp ฉันคิดเหมือนกันหมด ในความเป็นจริงมันดีกว่ามากที่จะจับคู่กับระเบียนที่แน่นอนที่เป็นปัญหาซึ่งฉันได้แก้ไขคำตอบด้วยการเปลี่ยนแปลงนี้ หวังว่านี้จะช่วยให้ผู้คนเรียนรู้การใช้ awk อย่างมีประสิทธิภาพยิ่งขึ้น
Dan Molding เมื่อ

14

Quanta เอาชนะฉันไป แต่ฉันจะรวมsedตัวแปรหากคุณเป็นเช่นนั้น:

nc localhost 9571 | sed -ne 's/^rating://p'

เหมือนอย่างที่ MadHatter พูดแม้ว่า โซลูชันปัจจุบันของคุณให้เสียงสมบูรณ์แบบ (แม้ว่าฉันจะต้องการ"^rating:"มากกว่าคำเพื่อให้แน่ใจว่าคุณจะได้รับสายที่คุณต้องการเท่านั้น)


ฉันรักsed! underutilized และ underappreciated ดังนั้น ...
เหม่ย

9

คุณยังสามารถใช้เปลือก:

nc localhost 9571 | 
while IFS=: read key val; do [[ $key = "rating" ]] && echo "$val"; done

นี่คือวิธีที่เร็วที่สุด - และป้องกันการวางไข่กระบวนการใด ๆ ncที่นอกเหนือ ดี!
เหม่ย

7

ใช่คุณสามารถ (และควร) ใช้ (หนึ่ง) awk แทน grep (สอง) และตัด:

$ nc localhost 9571 | awk -F: '/^rating:/ { print $2 }'

อย่าลืมจับคู่สายคุณให้ดีที่สุดเพื่อหลีกเลี่ยงข้อบกพร่องที่น่าเกลียด

  • /rating/ งาน
  • /^rating/ ดีกว่า (ปลอดภัยกว่า)
  • /^rating:/ ดีที่สุด (ในกรณีนี้)

4

มันสามารถ:

nc localhost 9571  | awk -F: '{ if ($1 == "rating") print $2 }' 

(ฉันไม่รู้ว่าคุณกำลังทำอะไรกับ localhost ด้านบนดังนั้นใช้เอาต์พุตของคุณเป็นอินพุตไปยังคำสั่ง awk ของฉันจากนั้นแทนที่ "cat" ด้วย "nc ... " - แต่มันควรจะใช้ได้)

แต่ทำไมคุณถึงทำเช่นนี้? วิธี UNIXคือการมีเครื่องมือขนาดเล็กจำนวนมากซึ่งแต่ละอันทำสิ่งหนึ่งได้ดีรวมตัวกันผ่านทางท่อแทนที่จะใช้เครื่องมือมัลติฟังก์ชั่นที่มีขนาดใหญ่กว่า คุณต้องเลือกหนึ่งบรรทัดที่ตรงกัน, เลือกหนึ่งฟิลด์จาก: grepเลือกบรรทัดที่มีการจับคู่และcutเลือกฟิลด์จากบรรทัดอินพุต; พวกเขาสมบูรณ์แบบสำหรับงาน แต่ถ้าคุณอยากทำทุกอย่างด้วย awk คุณก็ไปได้เลย


เหตุผลหนึ่งคือการใช้grepและcutต้องการวางไข่สองกระบวนการและการใช้awk(หรือsed) ต้องการเพียงหนึ่งกระบวนการ การวางไข่กระบวนการมีราคาแพง นอกจากนี้ยังแตกต่างจากการใช้perlหรือruby(et al) sedและawkมีน้ำหนักเบาด้านหน้ามากขึ้น
เหม่ย

2
ยุติธรรมเพียงพอแม้ว่าฉันจะทราบว่าขนาดของ awk binary ในระบบของฉัน (F15) คือ 360948 bytes ในขณะที่ grep และ cut binaries รวมกันเป็น 170824 ดังนั้นรอบน้อยลงด้วย fork เดียว + exec แต่มีหน่วยความจำเพิ่มขึ้นและ IO มากขึ้น เพื่อรับไบนารีปิดดิสก์ จริง ๆ แล้วฉันสงสัยว่าข้อพิจารณาใด ๆ เหล่านี้มีความสำคัญกับระบบที่ทันสมัย ​​แต่ถ้าคุณตั้งใจที่จะย่อเล็กสุดคุณก็จะไป!
MadHatter

Foo Bah: ขอบคุณสำหรับข้อเสนอการแก้ไขของคุณ แต่ quanta ทำโพสต์ในภายหลังกว่าของฉันซึ่งคล่องตัวกว่าคำแนะนำของคุณ ฉันต้องการของฉันเพราะง่ายกว่าสำหรับผู้ใช้ awk ระดับเริ่มต้นที่จะดูว่ามันทำงานอย่างไรและปฏิเสธการแก้ไขของคุณ ขอบคุณสำหรับความคิด แต่!
MadHatter

3

ในขณะที่คำตอบของควอนตั้มนั้นง่ายที่สุดและคำตอบที่ฉันเขียนด้วยฉันว่าคุณไม่รู้GNU awk (gawk) สามารถสร้างเครือข่ายได้หรือ คุณสามารถเขียนสิ่งทั้งหมดด้วย awk ถ้าคุณต้องการ:

BEGIN {
    FS = ":"
    f = "/inet/tcp/0/127.0.0.1/9571"
    while ((f |& getline) > 0)
        if ($1 ~ /^rating$/) {print $2}
}

สิ่งนี้อาจมีประโยชน์หากเซิร์ฟเวอร์ไม่ได้ติดตั้ง nc, nc ได้ จำกัด การใช้งานหรือถ้าคุณชอบ awk จริงๆ


โอ้ ดี เครือข่ายและตัวอย่างการประมวลผลร่วม
ดร. เอ็ดเวิร์ดมอร์เบียส

0

คุณยังสามารถใช

nc localhost 9571 | sed -n "s/^rating:\([\d]*\)/\1/p"

สิ่งนี้จะทำให้แน่ใจว่า "การให้คะแนน" เริ่มต้นบรรทัดและตัวเลขนั้นเป็นไปตาม rating:


0

ถ้า Perl เป็นตัวเลือก:

nc localhost 9571 | perl -F: -lane 'print $F[1] if /rating/'

-aautosplits แต่ละบรรทัดใน@Fอาร์เรย์
-F:ใช้:เป็นตัวคั่นฟิลด์แทนที่จะเป็นค่าเริ่มต้นของช่องว่าง
/rating/ส่งกลับจริงถ้าพบ regex เป็น
$F[1]องค์ประกอบที่สองของ@Fอาร์เรย์
Perl อาร์เรย์เริ่มต้นด้วยองค์ประกอบ 0 ในขณะที่ awk เริ่มต้นด้วย $ 1

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