awk กำหนดให้กับตัวแปรหลายตัวพร้อมกัน


9

ฉันพยายามดึงค่าตัวเลขสองค่าออกมาจากสตริงและกำหนดให้กับตัวแปรที่ใช้awk( gawkเป็นสิ่งที่ฉันใช้โดยเฉพาะ) ฉันต้องการดึงหมายเลขรุ่นหลักและรุ่นรองออกจากสตริงรุ่น tmux เป็นawkตัวแปรเช่น:

  • อินพุต: tmux 2.8; maj == 2และmin == 8
  • อินพุต: tmux 1.9a; maj == 1และmin == 9
  • อินพุต: tmux 2.10; maj == 2และmin == 10

สมมติว่าอินพุตของฉันมาจากtmux -Vstdin ฉันมีสิ่งต่อไปนี้:

tmux -V | awk '{
                  maj = +gensub(/([0-9]+)\..*/, "\\1", "g", $2);
                  min = +gensub(/.*\.([0-9]+).*/, "\\1", "g", $2);
                  # ...do something with maj and min...
               }'

งานนี้ แต่เป็นผู้ใช้จำนวนมากของความรู้ tmux ใช้if-shellใน.tmux.confไฟล์ (ซึ่งผมหวังว่าจะใช้สิ่งนี้) สามารถนำไปสู่จริงๆสายยาวในไฟล์ config ดังนั้นฉันสงสัยว่าถ้ามีวิธีที่จะรวมทั้งสองตัวแปร การมอบหมายให้เป็นคำสั่งเดียวเพื่อประหยัดพื้นที่ ... หรือวิธีอื่น ๆ ในการรวบรวมสองตัวแปรนี้จากอินพุตและประหยัดพื้นที่

ฉันกำลังคิดถึงสิ่งที่ชอบ:

awk '{ maj, min = +gensub(/([0-9]+)\.([0-9]+).*/, "\\1 \\2", "g", $2); }'

... ชนิดเช่นในหลาม awkแต่ที่ไวยากรณ์โดยเฉพาะอย่างยิ่งไม่ได้อยู่ใน มีอะไรอีกบ้างที่เป็นไปได้?

โปรดทราบว่าการอ่านไม่ได้กังวลจริงๆเพียงแค่ความยาว

คำตอบ:


9

โปรดทราบว่าgensubนี่เป็นgawkส่วนขยาย แต่จะไม่สามารถใช้ได้กับawkการใช้งานอื่น ๆ นอกจากนี้ยังทราบว่า+ผู้ประกอบการเอกไม่ได้บังคับให้แปลงเป็นตัวเลขในทุกawkการใช้งานที่ใช้+ 0เป็นแบบพกพามากขึ้น

ที่นี่คุณสามารถทำได้:

tmux -V | awk -F '[ .]' '{maj = $2+0; min = $3+0; print maj, min}'

หากคุณไม่สนใจการใช้awkส่วนขยายGNU คุณสามารถทำได้เช่นกัน:

tmux -V | awk -v FPAT='[0-9]+' '{maj = $1; min = $2; print maj, min}'

ขอบคุณสำหรับคำอธิบายเพิ่มเติมเกี่ยวกับความเข้ากันได้!
villapx

13

เนื่องจากคุณใช้ GNU awk คุณสามารถใช้รูปแบบ 3-arg ของmatch()เพื่อจัดเก็บกลุ่มการจับภาพหลายกลุ่ม:

awk '
    match($0, /([0-9]+)\.([0-9]+)/, m) {maj=m[1]; min=m[2]; print maj, min}
' <<END
tmux 2.8
tmux 1.9a
tmux 2.10
END
2 8
1 9
2 10

https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html


5

คุณสามารถแบ่งรุ่นเป็นอาร์เรย์ได้:

awk '{ split($2, ver, /[.a-z]/) }'

แล้วใช้ver[1]แทนmaj, แทนver[2]min

การเพิ่มa-zตัวคั่นจะลบอักษรตัวพิมพ์เล็กใด ๆ ออกจากหมายเลขเวอร์ชัน (โซลูชันอื่นดีกว่าที่นี่เนื่องจากแยกตัวเลขออกมาอย่างชัดเจน)


3

ผู้ใช้รายอื่นโพสต์คำตอบนี้และถูกลบภายหลัง ฉันคิดว่ามันมีประโยชน์:

ใช้split()ฟังก์ชั่นแบ่งสตริงรุ่นเป็นอาร์เรย์verจากนั้นเข้าถึงver[1]และver[2]มากกว่าmajและminตามลำดับ (หรือเพียงแค่เก็บค่าในตัวแปรเหล่านั้น):

tmux -V | awk '{ split($2, ver, /[.a-z]/); print ver[1], ver[2] }'

เครื่องหมายบวกที่นี่split()ไม่ใช่gawkส่วนขยาย (แม้ว่าจะมีอาร์กิวเมนต์ที่สี่เป็นทางเลือกseps)


+1 แต่เหตุใดจึงใช้/[.a-z]/เป็นอาร์กิวเมนต์ที่สาม (การแยกฟิลด์) ของsplitฟังก์ชันสตริงแทนที่จะเป็นเพียง"."?
Cbhihe

2
@Chih เห็นคำอธิบายเกี่ยวกับคำตอบของฉัน (ซึ่งฉันยกเลิกการลบเนื่องจาก villapx คิดว่ามันมีประโยชน์ขอบคุณ villapx!)
สตีเฟ่น Kitt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.