4 คะแนน โดย GN⁺ 2023-08-29 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • GNU awk จะวนผ่าน stdin และไฟล์โดยอัตโนมัติ และจัดการงานข้อความบน CLI ได้ด้วยการประกอบคำสั่งบรรทัดเดียวสำหรับ การกรอง·การแทนที่·การจัดการฟิลด์
  • /regexp/ และ !/regexp/ เป็นไวยากรณ์แบบย่อสำหรับตรวจสอบบรรทัดอินพุตปัจจุบัน และถ้าเงื่อนไขเป็นจริงจะมีการ พิมพ์ $0 ออกมาโดยปริยาย
  • sub จะแทนที่เฉพาะรายการที่ตรงกันตัวแรก ส่วน gsub จะแทนที่ทุกรายการที่ตรงกัน และถ้าละอาร์กิวเมนต์เป้าหมายไว้ จะใช้การแทนที่กับ บรรทัดอินพุตปัจจุบัน $0
  • ด้วยการแยกฟิลด์ตามช่องว่างและการใช้ $N, NF, $NF ทำให้ awk เหมาะกับงาน แบบอิงฟิลด์ เช่น การเลือกคอลัมน์เฉพาะหรือการประมวลผลตามเงื่อนไข
  • เมื่อเขียนชิ้นส่วน cond{action} ต่อกันและเพิ่ม BEGIN{}·END{} ก็สามารถสร้างโปรแกรมขนาดเล็กที่ไปไกลกว่าตัวกรองแบบง่าย ๆ และครอบคลุมทั้งสตริง ตัวเลข และ associative array ได้

วิธีการทำงานของ awk

  • awk สามารถกรองข้อความได้เหมือน grep, sed และยังมีความสามารถเชิงโปรแกรมสำหรับงานที่ซับซ้อนกว่านั้นด้วย
  • อินพุตสามารถรับจาก stdin หรือไฟล์ได้ และโดยปกติจะวนประมวลผลทีละบรรทัดพร้อมใช้เงื่อนไขและคำสั่งที่กำหนด
  • สามารถเข้าถึงทั้งบรรทัดอินพุตได้ผ่านตัวแปรพิเศษ $0
    • คำที่ถูกต้องจริง ๆ คือ input record แต่ในบทนี้จะอธิบายแบบทีละบรรทัด

การกรองและการพิมพ์ค่าเริ่มต้น

  • regular expression เขียนในรูป /.../ และเมื่อจะตรวจสอบว่าสตริงตรงกับ regex หรือไม่ จะใช้ไวยากรณ์ string ~ /regexp/
  • เงื่อนไขตรงข้ามเขียนเป็น string !~ /regexp/
  • ถ้าละสตริงที่จะตรวจสอบไว้ จะถือว่าใช้ $0
  • ถ้ามีแต่เงื่อนไขและไม่มีคำสั่ง เมื่อเงื่อนไขเป็นจริงจะพิมพ์ $0 ออกมาโดยอัตโนมัติ
    • awk '/regexp/' เป็นรูปย่อของ awk '$0 ~ /regexp/{print $0}'
    • awk '!/regexp/' เป็นรูปย่อของ awk '$0 !~ /regexp/{print $0}'
  • ในตัวอย่างจะแสดงการพิมพ์เฉพาะบรรทัดที่มี at หรือพิมพ์เฉพาะบรรทัดที่ไม่มี e เพื่อให้เห็นลำดับการทำงานพื้นฐานของการกรอง

สำนวนการพิมพ์ด้วย 1

  • ใน conditional expression ตัวเลขที่ไม่ใช่ 0 และ สตริงที่ไม่ว่าง จะถูกประเมินว่าเป็นจริง
  • awk '1' เป็นสำนวนที่ใช้กำหนดเงื่อนไขซึ่งเป็นจริงเสมอสำหรับทุกบรรทัดอินพุต
  • เมื่อไม่มีคำสั่ง เงื่อนไขที่เป็นจริงจะนำไปสู่การพิมพ์ $0 ดังนั้น awk '1' จึงพิมพ์อินพุตทั้งหมดออกมาตามเดิม
  • ผลลัพธ์เหมือนกับ awk '{print $0}' หรือ cat แบบตรง ๆ

การแทนที่: sub และ gsub

  • awk มีฟังก์ชัน sub และ gsub สำหรับค้นหาและแทนที่
  • sub(/:/, "-") จะแทนที่เฉพาะ : ตัวแรกในแต่ละบรรทัดอินพุตด้วย -
  • gsub(/:/, "-") จะแทนที่ : ทุกตัวในแต่ละบรรทัดอินพุตด้วย -
  • ทั้งสองฟังก์ชันรับ regular expression ที่จะจับคู่เป็นอาร์กิวเมนต์ตัวแรก และรับสตริงสำหรับแทนที่เป็นอาร์กิวเมนต์ตัวที่สอง
  • ถ้าไม่ได้ส่งสตริงอินพุตแยกต่างหากมา เป้าหมายเริ่มต้นคือ $0
  • เมื่อแทนที่สำเร็จ อินพุตเป้าหมายจะถูกแก้ไข
  • 1 หลังบล็อกแทนที่จะถูกตีความเป็น conditional expression ที่อยู่นอกบล็อก จึงทำให้มีการพิมพ์ $0 ที่ถูกแก้ไขแล้วออกมาอีกครั้ง
    • awk '{sub(/:/, "-")} 1' ให้ผลเหมือน awk '{sub(/:/, "-"); print $0}'
    • ต่อให้ใช้แค่ print เป้าหมายเริ่มต้นที่จะพิมพ์ก็ยังเป็น $0

เกณฑ์ในการเลือก grep, sed, awk

  • สำหรับการกรองบรรทัดแบบง่าย grep ที่ออกแบบมาเฉพาะทางอาจเร็วกว่า sed หรือ awk
  • งานแทนที่ข้อความ sed อาจเร็วกว่า awk
  • ความสามารถของเครื่องมือเหล่านี้ไม่ได้จับคู่กันแบบ 1:1 เสมอไป
    • หากจะทำ grep -o ด้วย sed หรือ awk มักต้องใช้หลายขั้นตอนมากกว่า
    • การค้นหาแบบ recursive มีให้เฉพาะ grep
  • ดูการอภิปรายที่เกี่ยวข้องได้ที่ unix.stackexchange: When to use grep, sed, awk, perl, etc

การประมวลผลแบบอิงฟิลด์

  • awk ถูกใช้งานบ่อยมากโดยเฉพาะกับ การประมวลผลแบบอิงฟิลด์
  • โดยปริยายจะแบ่งบรรทัดอินพุตตามช่องว่าง และเข้าถึงแต่ละฟิลด์ได้ด้วย $N
    • $2 คือฟิลด์ที่สอง
    • $NF คือฟิลด์สุดท้าย
    • NF คือจำนวนฟิลด์ทั้งหมดของบรรทัดอินพุตปัจจุบัน
  • ตัวอย่าง table.txt แสดงการประมวลผลระดับคอลัมน์อย่างกระชับ
    • พิมพ์ฟิลด์ที่สองของแต่ละบรรทัด
    • พิมพ์เฉพาะบรรทัดที่ฟิลด์สุดท้ายเป็นค่าลบ
    • เปลี่ยน b เป็น B เฉพาะในฟิลด์แรก
  • ไฟล์ตัวอย่างอยู่ในไดเรกทอรี example_files

โครงสร้างของคำสั่งบรรทัดเดียว

  • คำสั่งบรรทัดเดียวของ awk โดยทั่วไปมีรูปแบบดังนี้
awk 'cond1{action1} cond2{action2} ... condN{actionN}'
  • ถ้าไม่มีเงื่อนไข คำสั่งจะถูกเรียกทำงานเสมอ
  • ถ้าไม่มีคำสั่ง เมื่อเงื่อนไขเป็นจริงจะพิมพ์ $0
  • ภายในบล็อกสามารถคั่นหลาย statement ด้วยอัฒภาค ;
  • การเขียนหลายบล็อกต่อกันช่วยให้คำสั่งบรรทัดเดียวส่วนใหญ่แสดงการทำงานตามเงื่อนไขได้โดยไม่ต้องใช้ if อย่างชัดเจน
    • awk '$NF<0' table.txt จะพิมพ์เฉพาะบรรทัดที่ฟิลด์สุดท้ายเป็นค่าลบ
  • BEGIN{} จะทำงานก่อนเริ่มอ่านอินพุต
  • END{} จะทำงานหลังประมวลผลอินพุตทั้งหมดเสร็จแล้ว
  • รายละเอียดเพิ่มเติมของโอเปอเรเตอร์และ conditional expression อยู่ที่ gawk manual: Operators, gawk manual: Truth Values and Conditions

สตริงและตัวเลข

  • awk ตัดสินชนิดของค่าตามบริบทเพื่อให้สร้างวิธีแก้ปัญหาสั้น ๆ บน CLI ได้สะดวก
  • string literal เขียนไว้ใน เครื่องหมายอัญประกาศคู่
  • ตัวเลขสามารถใช้ได้ทั้งจำนวนเต็ม ทศนิยม และรูปแบบวิทยาศาสตร์
  • BEGIN{} ใช้ได้แม้ตอนรันโปรแกรม awk โดยไม่มีอินพุตภายนอก
  • ตัวแปรสามารถเก็บได้ทั้งตัวเลขและสตริง
    • ตัวอย่าง: a=5; b=2.5; print a+b
    • ถ้าวางสตริงเรียงต่อกันจะเป็นการเชื่อมสตริง
  • ตัวแปรที่ยังไม่ได้กำหนดค่า จะทำงานเหมือนสตริงว่างในบริบทของสตริง และเหมือน 0 ในบริบทของตัวเลข
  • เมื่อใช้สตริงในนิพจน์ตัวเลข จะมีการบังคับแปลงเป็นตัวเลข
    • ถ้าสตริงไม่ได้ขึ้นต้นด้วยรูปแบบตัวเลขที่ถูกต้อง จะถูกมองเป็น 0
    • ช่องว่างด้านหน้าจะถูกละเลย
  • เมื่อเชื่อมสตริงเข้ากับตัวเลข ตัวเลขจะถูกแปลงเป็นสตริง
  • รายละเอียดเพิ่มเติมดูได้ที่ gawk manual: Constant Expressions และ gawk manual: How awk Converts Between Strings and Numbers

อาร์เรย์

  • อาร์เรย์ของ awk เป็น associative array และทำงานเป็นคู่คีย์-ค่า
  • คีย์อาจเป็นตัวเลขหรือสตริงก็ได้ แต่คีย์ที่เป็นตัวเลขจะถูกแปลงเป็นสตริงภายใน
  • สามารถใช้อาร์เรย์หลายมิติได้เช่นกัน
  • ในตัวอย่างมีการเก็บและเข้าถึงค่าด้วยคีย์สตริง เช่น student["id"], student["name"]
  • สามารถตรวจสอบการมีอยู่ของคีย์ได้ในรูป "id" in student
  • รายละเอียดเพิ่มเติมอยู่ที่ gawk manual: Arrays

แบบฝึกหัดและขั้นถัดไป

  • บทนี้แนะนำอย่างย่อถึงรูปย่อของไวยากรณ์ awk, การกรอง, การแทนที่, การจัดการฟิลด์, การแปลงชนิดข้อมูล และอาร์เรย์
  • บทถัดไปจะกล่าวถึง regular expression และความสามารถที่แนะนำในบทนี้จะยังถูกใช้ต่อในตัวอย่างต่าง ๆ
  • คุณสามารถลองเปลี่ยนหมายเลขฟิลด์ หรือทดลองกับอินพุตรูปแบบอื่น เช่น หมายเลขฟิลด์ที่เป็นค่าลบหรือทศนิยม เพื่อให้คุ้นเคยกับไวยากรณ์มากขึ้น
  • แอป TUI สำหรับฝึกแบบโต้ตอบติดตั้งได้จากรีโพซิทอรี AwkExercises และวิธีใช้อยู่ใน app_guide.md
  • แบบฝึกหัดทั้งหมดรวมอยู่ใน Exercises.md และเฉลยอยู่ใน Exercise_solutions.md

1 ความคิดเห็น

 
GN⁺ 2023-08-29
ความคิดเห็นจาก Hacker News
  • ผมชอบ awk และใช้ค่อนข้างบ่อย หนึ่งในการใช้งานหลักคือใช้มันเหมือน sed แบบมีสถานะ
    เช่น แมตช์เฉพาะเมื่อบรรทัดหนึ่งปรากฏหลังบรรทัดเฉพาะก่อนหน้า จึงมีประโยชน์เวลาทำ linter ชั่วคราว
    ล่าสุดผมทำตัวตรวจสอบเพื่อหาไฟล์ migration ที่มี CREATE INDEX ซึ่งอาจเป็นปัญหากับตารางขนาดใหญ่มาก ๆ โดยไม่ได้ใส่ CONCURRENTLY แต่คำสั่ง SQL อาจกินหลายบรรทัด ทำให้แมตช์แบบง่าย ๆ ได้ยาก
    awk สามารถ ติดตามสถานะ ข้ามหลายบรรทัดได้ เช่น “กำลังอยู่ในคำสั่ง create”, “กำลังสร้าง index” ดังนั้นสคริปต์ที่ปะติดปะต่อแบบลวก ๆ ก็ทำงานได้ดีมาประมาณ 1 ปีแล้ว

    • สักวันคงต้องเรียน awk แต่ระหว่างนั้นผมก็ได้เรียนรู้ ฟีเจอร์เชิงสถานะ ที่ลึกขึ้นของ sed
      ถ้าต้องการพิมพ์บรรทัดปัจจุบันเฉพาะเมื่อบรรทัดก่อนหน้าตรงกับแพตเทิร์นหนึ่ง ๆ ก็ทำได้ประมาณ sed -ne 'x' -e '/PREV/ {x; /CURR/ p; x}'
      ตัวอย่าง: echo -e "PREV\nCURR\nCURR\nCURR\nPREV\nRED" | sed -ne 'x' -e '/PREV/ {x; /CURR/ p; x}' จะพิมพ์แค่ CURR
      นี่เป็นวิธีใช้ hold buffer ของ sed โดยใช้ -n เพื่อปิดการพิมพ์ตามค่าเริ่มต้น แล้วใช้ p เพื่อพิมพ์เฉพาะบรรทัดที่ต้องการ
      x จะสลับบรรทัดปัจจุบันกับ hold buffer และภายในบล็อก /PREV/ { ... } จะสลับกลับอีกครั้ง จากนั้นพิมพ์เฉพาะเมื่อบรรทัดปัจจุบันมี CURR
      x ตัวสุดท้ายมีไว้เพื่อสลับกลับ เผื่อกรณีที่การแมตช์ซ้อนทับกัน
      แน่นอนว่าสคริปต์ awk มีแนวโน้มจะเรียบง่ายและตรงไปตรงมากว่ามาก แต่ sed ก็ทำแบบนี้ได้เช่นกัน
      เวลาที่ใช้เรียนรู้นี่อาจเอาไปลงกับ awk จะคุ้มกว่า แต่บทเรียน https://www.grymoire.com/Unix/Sed.html ดีมากจนผมเรียนรู้แทบทุกอย่างที่รู้เกี่ยวกับ sed จากที่นี่
    • ถ้าแชร์ตัวอย่างที่ใช้ awk ติดตามสถานะของ SQL ได้ก็น่าจะดี
  • ถ้าอ่านเธรดนี้อยู่ ก็น่าจะสนใจ “Ask HN: Share a shell script you like” เมื่อ 2 สัปดาห์ก่อนด้วย
    มีคอมเมนต์ 78 รายการ จึงไม่ได้คึกคักเท่าที่คาดไว้ แต่ก็น่าเอาไว้ดูอ้างอิง: https://news.ycombinator.com/item?id=37112991

  • ผมยังคงสนใจ Awk อยู่เล็กน้อย ควบคู่กับ Lisp และอย่างอื่น ๆ และในปี 2022 ก็ทำ cppawk ขึ้นมา: https://www.kylheku.com/cgit/cppawk/about/
    cppawk เพิ่ม ความสามารถด้านพรีโปรเซสเซอร์ ให้กับ Awk
    มี loop macro ที่รองรับหลาย clause สามารถประกอบ clause เพื่อทำ parallel iteration หรือ Cartesian product iteration ได้ และผู้ใช้ก็ขยายเองได้ด้วย
    แค่เขียน macro ง่าย ๆ 5 ตัวก็สามารถนิยาม clause ใหม่ได้
    ถ้าใช้ Awk อยู่ก็น่าจะมีประโยชน์ มีเอกสารเป็น man page หลายหน้า และมี unit test ที่รันบน gawk กับ mawk ด้วย

  • อาจเป็นเพราะสัญชาตญาณผู้ดูแลระบบยุคเก่าของผมโผล่ออกมา แต่ผมไม่ค่อยเห็นข้อดีของ awk เมื่อเทียบกับการเขียนสิ่งเดียวกันด้วย Perl ตรง ๆ
    ผมเห็น shell script แย่ ๆ ที่ผู้ดูแลระบบจูเนียร์ทำไว้เยอะมาก และทุกครั้งก็คิดว่า “ส่วนประมวลผลข้อความนี่ถ้าใช้ Perl คงสะอาดกว่านี้มาก”

    • ถ้าอยู่ในสภาพแวดล้อมที่ใช้ Perl เป็นประจำ คำพูดนั้นก็สมเหตุสมผลมาก
      สำหรับผม awk เป็นหนึ่งในไม่กี่ภาษาที่แม้จะวางทิ้งไว้หลายเดือน ก็ใช้เวลาแค่ 10 นาทีก็กลับมาจับทางได้อีก
      มันมีความเป็น intuitive และเข้ากับเครื่องมือ command line ทั่วไปได้อย่างเป็นธรรมชาติ
    • ถ้าเทียบ Awk กับ Perl สำหรับการเขียนสคริปต์ ผมชอบ Perl หรือ Python มากกว่า
      แต่บทความนี้พูดถึง คำสั่งบรรทัดเดียว สั้น ๆ สำหรับงานชั่วคราว และในกรณีแบบนั้น sed/awk ดีกว่า Perl
      ถ้ารู้ Perl อยู่แล้ว ก็ไม่จำเป็นต้องเรียนเครื่องมือเพิ่ม ใช้ Perl ต่อไปก็ได้
    • จุดแข็งของ Awk คือ read loop ที่มีให้ฟรี การแยกฟิลด์ และโมเดลการแมตช์แพตเทิร์น/เงื่อนไข
      ตัวภาษาเองก็ “พอใช้ได้” แต่ใช้งานได้เพียงพอ
      แน่นอนว่า Perl ก็ทำได้ทั้งหมด แต่ต้องเขียน boilerplate ที่ awk ให้มาฟรีเอง
      ข้อดีของภาษา Perl สำหรับผมไม่ได้มากพอให้ทิ้ง awk และเพราะผมใช้ awk กับงานประมวลผลข้อมูลและปรับแต่งไฟล์แบบครั้งเดียว มากกว่าจะใช้เป็น “scripting” จึงไม่ได้โหยหาความลึกของ Perl
      ถ้าต้องการฟีเจอร์ที่ลึกกว่านั้น ผมก็ไปใช้ที่อื่น
    • แทบไม่มีข้อได้เปรียบทางเทคนิคอะไร และฟีเจอร์ของ Perl ตั้งใจให้ใกล้เคียงกับ superset ของ awk
      คนรุ่นนี้ไม่ได้เรียน Perl กัน จึงดูเหมือนกำลังค้นพบไอเดียการประมวลผล stream ขึ้นมาใหม่ผ่าน awk
      awk เป็นไอเดียที่ยอดเยี่ยมตามมาตรฐานปลายทศวรรษ 1970 และเป็นนวัตกรรมจริง ๆ ที่คู่ควรแก่การเลียนแบบ
      ต่อมา Perl ก็เลียนแบบและก้าวข้ามมันไป แต่กลับถูกลืม ดังนั้นการเห็น awk ถูกค้นพบใหม่จึงออกจะน่าเขินเล็กน้อย
    • ไม่ได้ประชดนะ แต่อยากรู้ว่าทำไม Perl ถึงดีกว่า Python สำหรับงานสคริปต์
  • สิ่งหนึ่งที่ไม่ค่อยมีคนรู้เกี่ยวกับ gawk คือโดยปกติมันมาพร้อม ส่วนขยาย ที่มีประโยชน์
    สามารถเข้าถึงฟังก์ชันอย่าง readdir(), ord(), chr(), gettimeofday(), sleep() ได้
    https://www.gnu.org/software/gawk/manual/html_node/Extension-Samples.html

  • คำสั่ง awk แบบบรรทัดเดียวทรงพลังจริง ๆ
    คำถามที่ยากคือคุ้มไหมที่จะลงทุนกับการเขียนโปรแกรม awk ที่ซับซ้อนกว่าเดิม
    ถ้างานประมวลผลต้องใช้ตรรกะที่ซับซ้อน awk ก็มีให้ แต่ให้มาในรูปแบบสั้น ๆ อ่านยาก ๆ สไตล์ยุคคอมพิวเตอร์ยุคแรก
    แต่ถ้าเลือกทางเลือกสมัยใหม่ ก็มีภาระของมันเอง โดยเฉพาะบางอย่างอย่าง pandas ที่อาจไม่ค่อย intuitive และยังอาจมีปัญหาเรื่องประสิทธิภาพด้วย

    • ปัญหาใหญ่สำหรับผมคือเรื่อง ไลบรารี
      แม้แต่ไฟล์ฟังก์ชัน common สำหรับใช้ส่วนตัวก็ยังไม่รู้สึกว่ารองรับดีนัก และดูเหมือนไม่มีวิธีที่เหมาะ ๆ ในการนำไลบรารี third-party มาใช้
      พอเริ่มต้องมี helper function และเริ่มแยกเป็นหลายบรรทัด ปกติก็จะย้ายไป Python
      แล้วโปรแกรมก็ใหญ่ขึ้น 2–3 เท่า จนต้องถอนหายใจ
      Ruby เป็นตัวแทน awk ที่ยอดเยี่ยม แต่ถ้าเพื่อนร่วมงานไม่รู้จัก Ruby ก็คาดหวังให้ดูแลรักษาต่อได้ยาก
    • ก่อนยุค ChatGPT ผมไม่ชอบคำสั่ง awk/sed แบบบรรทัดเดียวที่อ่านยาก
      เดี๋ยวนี้พอเอาคำสั่งอ่านยากพวกนั้นไปแปะให้ AI มันก็อธิบายทีละขั้นตอนได้ค่อนข้างดี เลยพอรับได้มากขึ้น
      ถึงอย่างนั้นเพราะเรื่องความสามารถในการทำ unit test ผมยังชอบ Python อีกไม่กี่บรรทัดมากกว่า แต่สำหรับงานแปลงข้อมูลเร็ว ๆ บางครั้งก็ไม่จำเป็นต้องมี unit test ตั้งแต่แรก
  • เปิดตัวอีบุ๊กเวอร์ชันใหม่ของ “CLI text processing with GNU awk
    สามารถเรียนรู้คำสั่ง GNU awk ตั้งแต่ระดับเริ่มต้นถึงขั้นสูงแบบเป็นขั้นเป็นตอน ผ่านตัวอย่างและแบบฝึกหัดหลายร้อยรายการ ครอบคลุมเชิงลึกทั้งการประมวลผลฟิลด์ การกรอง การจัดการหลายไฟล์ วิธีแก้ปัญหาที่พึ่งพาหลายเรคอร์ด การเปรียบเทียบเรคอร์ดและฟิลด์ระหว่างไฟล์ การหาข้อมูลซ้ำโดยยังรักษาลำดับอินพุตไว้ regex และอื่น ๆ
    PDF/EPUB: https://learnbyexample.gumroad.com/l/gnu_awk (ฟรีจนถึง 31 สิงหาคม 2023)
    เวอร์ชันเว็บ: https://learnbyexample.github.io/learn_gnuawk/
    ซอร์ส Markdown และไฟล์ตัวอย่าง: https://github.com/learnbyexample/learn_gnuawk
    แอป TUI แบบโต้ตอบสำหรับฝึกทำแบบฝึกหัด: https://github.com/learnbyexample/TUI-apps/blob/main/AwkExercises
    ชุดบันเดิล Magical one-liners ที่รวมคำสั่งบรรทัดเดียวของ grep, sed, awk, perl, ruby ราคา $5: https://learnbyexample.gumroad.com/l/oneliners/new_awk_release, บันเดิลอีบุ๊กครบทั้ง 13 เล่ม ราคา $12: https://learnbyexample.gumroad.com/l/all-books/new_awk_release
    ฟีดแบ็กใด ๆ ไม่ว่าจะเป็นคำผิด ข้อผิดพลาดในโค้ด ส่วนที่ใช้ได้ดีหรือใช้ได้ไม่ดี ล้วนช่วยได้มาก
    การถกเถียงก่อนหน้านี้มี https://news.ycombinator.com/item?id=15549318 และ https://news.ycombinator.com/item?id=22758217

    • สงสัยว่ามีคนจ่ายเงินจริงให้สื่ออย่าง Magical one-liners มากแค่ไหน และเคยลองโมเดล “ดูแล้วค่อยเลือกจ่าย” บ้างไหม
      มันอาจมีประโยชน์พอให้จ่าย $5 หรือ $15 ก็ได้ แต่ก็อาจไม่ต่างจากสิ่งที่ผมเก็บไว้แล้วในไฟล์คำสั่งบรรทัดเดียวส่วนตัว เลยลังเลที่จะจ่ายเงินเพื่อเช็กดู
    • เห็นได้ชัดว่าลงแรงไว้มาก และโดยเฉพาะผมชอบ แอปพลิเคชัน TUI
      สงสัยว่าเวอร์ชันเว็บจะยังคงฟรีต่อไปหลังวันที่ 31 สิงหาคมด้วยหรือไม่
  • เมื่อก่อนเคยทำกอล์ฟ วาดรูปหัวใจด้วย AWK ไว้: https://gist.github.com/auselen/906a53b47a7d616b080dbef85eb8f776

  • 99.9% ของการใช้ awk คือใช้แยกบรรทัดพร้อมทิ้งช่องว่างต่อเนื่อง
    เช่น: echo "key: value" | awk '{print $1}'
    ถ้ามีทางเลือกที่ง่ายกว่านี้ก็คงดี

    • น่าพิจารณา https://github.com/c-blake/bu/blob/main/doc/cols.md
      เขียนด้วย Nim แต่ก็อาจไม่ใช่อุปสรรคใหญ่ และเครื่องมืออื่น ๆ ใน bu/ ก็น่าสนใจได้เช่นกัน
    • ใช้ cut ก็ทำได้: echo "key: value" | cut -wf 2
      แต่จะง่ายกว่าจริงไหมยังเถียงกันได้
      ลองตรวจดูแล้ว GNU cut ไม่มี -w จึงเป็นของ BSD เท่านั้น
      สุดท้ายคงใช้ awk ดีกว่า
    • https://github.com/sstadick/hck และ https://github.com/theryangeary/choose ก็น่าลองดู
      ทั้งสองเป็นทางเลือกแทน cut/awk และรองรับการแยกตาม regex ด้วย แต่เท่าที่จำได้ไม่ตัดช่องว่างหัว/ท้าย
      เครื่องมือที่ผมทำเอง https://github.com/learnbyexample/regexp-cut เป็นเครื่องมือคล้าย cut ที่ใช้ awk เพื่อให้แยกตาม regex, ใช้ดัชนีติดลบ ฯลฯ ได้ และด้วยพฤติกรรมพื้นฐานของ awk จึงจัดการช่องว่างหัว/ท้ายได้ด้วย
    • น่าจะตั้งใจพูดว่า echo "key: value" | awk '{print $2}' มากกว่า
  • ก่อนหน้านี้ผมเคยเขียน สคริปต์ diff2html ที่พอร์ตมาจาก bash ด้วย awk และด้วยเหตุผลที่ชัดเจน มันเร็วกว่าเยอะ
    ฝั่ง awk อ่านง่ายกว่าสคริปต์ bash มาก และผมสามารถเรียนภาษา ดีบัก ทำความเข้าใจบั๊ก แล้วแก้ได้ภายในคืนเดียว
    ไม่รู้ว่านี่เป็นวิธีเขียนแบบ awk ที่เป็นสำนวนปกติหรือเปล่า แต่รู้สึกว่าเป็นภาษาที่ดีจริง ๆ
    https://github.com/berry-thawson/diff2html/blob/master/diff2html.sh