====== AWK ======
>> เนื้อหาส่วนนี้เป็นส่วนหนึ่งของวิชา [[:204223-52|Practicum in Computer Engineering]]
[[http://en.wikipedia.org/wiki/AWK|AWK]] เป็นภาษาโปรแกรมและเครื่องมือในการประมวลผลข้อความ เราจะหัดใช้ AWK อย่างง่าย ๆ โดยพิจารณาจากตัวอย่าง
===== ตัวคั่นและการพิมพ์ =====
เราสามารถสั่งให้ awk ทำงานในลักษณะคล้าย ๆ กับคำสั่ง ''cut'' ได้ โดยระบุตัวคั่นระหว่างฟิลด์ด้วย option ''-F'' (ถ้าไม่ระบุจะถือว่าเป็นช่องว่าง) และอ้างถึงแต่ละฟิลด์ด้วยตัวแปร ''$1'', ''$2'', เป็นต้น (ส่วนตัวแปร ''$0'' จะแทนบรรทัดทั้งบรรทัด)
ยกตัวอย่างเช่น ถ้าเรามีแฟ้ม ''/etc/password'' ดังนี้
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
และเราต้องการพิมพ์ username กับ home directory เราจะสั่ง
awk -F: '{ print $1, $6 }' /etc/passwd
และได้ผลลัพธ์เป็น
root /root
daemon /usr/sbin
bin /bin
sys /dev
sync /bin
games /usr/games
man /var/cache/man
lp /var/spool/lpd
อาร์กิวเมนต์ตัวสุดท้ายคือไฟล์ที่ต้องการประมวลผล (ใส่ได้หลายไฟล์) หรืออาจจะส่งข้อมูลให้โดยการ redirection ก็ได้
อาร์กิวเมนต์ ''{ print $1, $6 }'' ที่เราส่งให้กับโปรแกรม AWK คือโปรแกรมสำหรับประมวลผล ซึ่งจะประกอบไปด้วยคู่ของ ''pattern'' และ ''action'' ในลักษณะดังนี้
pattern { action }
โดย ''action'' จะทำงานเมื่อบรรทัดที่อ่านเข้ามาตรงกับ ''pattern'' ในกรณีที่ไม่ระบุ ''pattern'' ก็จะทำงานกับทุก ๆ บรรทัด
> :-) **แบบฝึกฟัด 5.1** แฟ้ม ''twocols'' ประกอบไปด้วยข้อมูลแบบตัวเลขบรรทัดละสองจำนวน เขียนคำสั่ง 1 บรรทัด ที่แสดงข้อมูลจากแฟ้มดังกล่าวที่สลับคอลัมน์แรกกับคอลัมน์ที่สอง
===== เรียงชื่อแบบสุ่ม =====
AWK มีฟังก์ชันที่เราสามารถเรียกใช้ได้มากมาย (สามารถดูได้โดยสั่ง ''man awk'') หนึ่งในนั้นคือฟังก์ชัน ''rand()'' คำสั่งด้านล่างพิมพ์รายการรหัสประจำตัวจากแฟ้ม ''sel-id'' เรียงลำดับแบบสุ่ม
awk '{print rand(), $1}' sel-id | sort -n | cut -d ' ' -f2
> :-) **แบบฝึกหัด 5.2** อธิบายการทำงานของคำสั่งข้างต้นคร่าว ๆ
คำสั่งดังกล่าวสามารถนำมาดัดแปลงเพื่อแบ่งกลุ่มนิสิตออกเป็นกลุ่มย่อย ๆ 5 กลุ่มแบบสุ่ม โดยผลลัพธ์ที่ต้องการมีลักษณะดังนี้
49054869,1
49552987,1
49055338,1
...
49055338,1
49552052,2
49554967,2
...
นั่นคือมีรายชื่อนิสิต เรียงตามกลุ่มที่สุ่มแล้ว ไม่จำเป็นที่แต่ละกลุ่มจะต้องมีจำนวนนิสิตเท่ากัน (แต่ถ้าเป็นการจัดกลุ่มแบบสุ่มจำนวนคนจะใกล้เคียงกัน)
> :-) **แบบฝึกหัด 5.3** เขียนคำสั่งเพื่อจัดกลุ่มนิสิตดังกล่าว (ใช้เลขประจำตัวจากไฟล์ ''sel-id'')
**คำใบ้:** ใช้ฟังก์ชัน ''int'' เพื่อปัดเศษ
===== ตัวแปรและรูปแบบ (pattern) =====
สำหรับ pattern ที่ใช้ตรวจสอบเงื่อนไขของบรรทัดเพื่อเข้าทำงานใน action นั้น อาจเป็น ''BEGIN'' (ทำเมื่อเริ่ม), ''END'' (ทำเมื่อสิ้นสุด), หรือเป็นเงื่อนไขก็ได้ เราสามารถระบุเงื่อนไขเป็น regular expression ซึ่งจะเป็นจริงถ้าบรรทัดนั้นมี expression นั้น หรืออาจระบุการทดสอบกับตัวแปรก็ได้ เช่น pattern ว่า ''$1 ~ /[a-z]+/'' ทดสอบว่าฟิลด์แรกมีแค่ตัวอักษร a - z เท่านั้น
คำสั่งด้านล่างนับจำนวนนิสิตใน ''sel-id'' แยกเป็นนิสิตภาคปกติกับภาคพิเศษ
awk 'BEGIN { n=0; s=0; } /^4905/ { n++; } /^4955/ { s++; } END { print n,s }' sel-id
สังเกตว่าโปรแกรมด้านล่างเริ่มจะยาว เราสามารถเก็บโปรแกรมลงในแฟ้มก่อน แล้วค่อยเรียกใช้ได้ โดยใช้ option ''-f'' โปรแกรมข้างต้นเขียนให้อ่านง่ายขึ้นได้ดังนี้
BEGIN { n=0; s=0; }
/^4905/ { n++; }
/^4955/ { s++; }
END { print n,s }
ถ้าเราเก็บโปรแกรมดังกล่าวในแฟ้มชื่อ ''countstd'' เราจะเรียกใช้โดยสั่ง ''awk -f countstd sel-id''
===== อ่านเพิ่มเติม =====
* [[http://cholwich.org/wordpress/2008/07/05/awk/|บทความ AWK ภาษาไทย]] จากบล็อก Cholwich
* [[http://en.wikipedia.org/wiki/AWK|วิกิพีเดีย (อังกฤษ)]]
* [[http://awk.info/|AWK community portal]] ที่มีตัวอย่าง[[http://awk.info/?awk1line|การใช้ awk แบบหนึ่งบรรทัด]]มากมาย