Linux Shell : เปลี่ยนแปลงข้อความที่ต้องการด้วย sed

คำสั่ง sed (Stream EDitor) เป็นอีกคำสั่งพื้นฐานของลีนุกซ์ที่ใช้กันบ่อย เพื่อเปลี่ยนแปลงข้อความเท็กซ์จากต้นทาง (input) ให้ได้ผลลัพธ์ออกมาตามที่ต้องการ (output)

นอกจากลีนุกซ์แล้ว บนยูนิกซ์ (Unix) เกือบทุกตระกูลรวมทั้ง Mac OS จะมีคำสั่ง sed ติดตั้งมาให้โดยดีฟอลต์ จะแตกต่างกันตรงเวอร์ชันที่ติดตั้ง ของลีนุกซ์จะใช้เป็น GNU sed ซึ่งจะมีออปชันให้ใช้มากหน่อย แต่ในที่นี้ขอยกตัวอย่างแค่การใช้ sed แบบพื้นฐานที่สามารถใช้ได้กับ sed ทุกเวอร์ชัน

สมมติว่าเรามีไฟล์เท็กซ์ชื่อ reports.txt โดยมีข้อความในไฟล์ดังนี้

$ cat reports.txt
id;name;score;remark
1;alice;89;good
2;bob;73;well done
3;chris;92;very good
4;dan;100;excellent
5;eric;80;good

เริ่มต้น เราต้องการเปลี่ยนข้อความหรือตัวอักษร ; ให้เป็นเครื่องหมาย , สามารถใช้คำสั่ง sed ระบุออปชันในการเปลี่ยนแปลงข้อความดังนี้

$ sed 's/;/,/' reports.txt
id,name;score;remark
1,alice;89;good
2,bob;73;well done
3,chris;92;very good
4,dan;100;excellent
5,eric;80;good

คำอธิบายการใช้คำสั่ง sed

  • พิมพ์คำสั่ง sed ตามด้วยออปชันหรือคำสั่งในการเปลี่ยนแปลง (command) อยู่ในเครื่องหมาย ‘ ‘ แล้วตามด้วยชื่อไฟล์
  • s ที่อยู่ในเครื่องหมาย ‘ ‘ หมายถึงให้มีการแทนที่ (substitute)
  • ใน sed รูปแบบการใช้คำสั่ง s คือ
   's/REGEXP/REPLACEMENT/FLAGS'

REGEXP คือรูปแบบ Regular Expression ของข้อความที่ต้องการเปลี่ยน จากตัวอย่างข้างบนเราระบุแค่ ; คือให้แทนที่ข้อความตัวอักษรตัวนี้

REPLACEMENT คือให้แทนที่ข้อความด้วยอะไร จากตัวอย่างเราจะแทนที่ด้วยข้อความหรือตัวอักษร ,

FLAGS จากตัวอย่างข้างบนเราไม่ได้ระบุ

คำสั่ง sed จะจัดการข้อความทีละบรรทัดตามคำสั่งที่เราระบุ ในที่นี้คือ s คือให้แทนที่ (substitute)

จะเห็นว่าผลลัพธ์ที่ได้ ในแต่ละบรรทัดจะมีการเปลี่ยนแปลงจาก ; ไปเป็น , แค่บรรทัดละตัวอักษรเท่านั้น

หากเราต้องการให้มีการเปลี่ยนแปลงตัวอักษรจาก ; ให้เป็น , ทั้งหมด เราต้องระบุ FLAGS ‘g’

ตัวอย่างการใช้ FLAGS ‘g’ เพื่อแทนที่ข้อความทั้งหมดในแต่ละบรรทัด

$ sed 's/;/,/g' reports.txt
id,name,score,remark
1,alice,89,good
2,bob,73,well done
3,chris,92,very good
4,dan,100,excellent
5,eric,80,good

ตอนนี้ตัวอักษร ; ถูกแทนที่ด้วย , ทั้งหมดแล้ว

นอกจากจะใช้ sed แบบระบุชื่อไฟล์แล้ว คำสั่ง sed สามารถรับ input มาจากคำสั่งอื่นก็ได้ โดยใช้เครื่องหมาย |

เช่นหากเราต้องการแก้ไขเพิ่มเติม เช่นเติมเครื่องหมาย , ต่อท้ายแต่ละบรรทัด ก็สามารถทำได้ดังนี้

$ sed 's/;/,/g' reports.txt | sed 's/$/,/'
id,name,score,remark,
1,alice,89,good,
2,bob,73,well done,
3,chris,92,very good,
4,dan,100,excellent,
5,eric,80,good,

เครื่องหมาย | ใช้สำหรับรับ output ที่ได้จากการรันคำสั่งซ้ายมือ เพื่อส่งไปเป็น input ของคำสั่งขวามือ

ด้านขวามือเราใช้ sed ระบุคำสั่ง s เพื่อแทนที่ข้อความเหมือนเดิม แต่ในที่นี้เราใช้เครื่องหมาย $ ซึ่งเป็น REGEXP ที่หมายถึงจุดสิ้นสุดของแต่ละบรรทัดก่อนขึ้นบรรทัดใหม่ เราต้องการแทนที่จุดสิ้นสุดนี้ของแต่ละบรรทัด โดยการเติมเครื่องหมาย ,

ถ้าต้องการเปลี่ยนจุดเริ่มต้นของแต่ละบรรทัด ให้ใช้เครื่องหมาย ^

ที่จริงถ้าคุณใช้ Regular Expression ได้ชำนาญ คุณสามารถเปลี่ยนข้อความหลายอย่าง ซึ่งถ้าใช้โปรแกรมอื่นๆ อาจทำได้ยากมากหรืออาจต้องเขียนโปรแกรมช่วย

หมายเหตุ คำสั่ง sed บนยูนิกซ์บางตัวอาจไม่รองรับการใช้ REGEXP แบบนี้ ตัวอย่างนี้ทดลองบนลีนุกซ์ CentOS 7

ตัวอย่างเช่น เปลี่ยนตัวอักษรเริ่มต้นของแต่ละคำให้เป็นตัวพิมพ์ใหญ่

$ sed 's/;/,/g' reports.txt | sed 's/\<[a-z]/\U&/g'
Id,Name,Score,Remark
1,Alice,89,Good
2,Bob,73,Well Done
3,Chris,92,Very Good
4,Dan,100,Excellent
5,Eric,80,Good

คำอธิบาย

  • \<[a-z]    คือตัวอักษรขึ้นต้นของแต่ละคำ
  • &    ข้อความที่ต้องการแทนที่
  • \U    ให้แทนที่ด้วยตัวพิมพ์ใหญ่

ลองนำไปใช้กันดูนะครับ

ข้อมูลอ้างอิง

Leave a Reply

Your email address will not be published.