วันอาทิตย์ที่ 2 มีนาคม พ.ศ. 2551

sed - stream editor (4)

3. ถ้าใน pattern มี / เป็นส่วนประกอบ

นั่นหมายความว่า คำสั่ง s จะมีปัญหาถ้าเราไม่หลบเครื่องหมายก่อน เพราะในคำสั่งมันต้องใช้ / เป็นตัวคั่นนั่นเอง

เช่น ถ้าต้องการแทนคำว่า /usr/local/bin ด้วยคำว่า /common/bin ของทั้งไฟล์ new.txt ก็จะต้องทำแบบข้างล่างนี้

sed 's/\/usr\/local\/bin/\/common\/bin/' new.txt
มองดูแล้วน่าเกลียดมาก อ่านไม่รู้เรื่องเลย ซึ่งลักษณะแบบนี้เขาเรียกว่า Packet Fence

ก็คือเวลาพิมพ์ เราจะต้องคิดว่าเรากำลังแทนที่ข้อความ \/usr\/local\/bin ด้วยคำว่า \/common\/bin

นอกจากจะใช้เครื่องหมาย / มาทำเป็นตัวคั่นของคำสั่งแทนที่แล้ว จริงๆแล้วเรายังสามารถใช้เครื่องหมายอื่นๆได้ด้วย ดูจากตัวอย่างข้างล่าง

sed 's_/usr/local/bin_/common/bin_' new.txt
sed 's:/usr/local/bin:/common/bin:' new.txt
sed 's|/usr/local/bin|/common/bin|' new.txt

ซึ่งทำให้เราไม่ต้องมานั่งเขียน packet fence ให้ยุ่งยาก (แต่ในสิ่งที่เราต้องการจะแทนที่และนำไปแทนที่จะต้องไม่มีสัญลักษณ์ที่ใช้แทนอยู่ในนั้น)

sed - stream editor (3)

2. แทนที่โดยใช้ &

โดยหลักแล้ว sed สามารถใช้ & เพื่ออ้างอิงถึงสิ่งที่กำลังทำการค้นหาได้ เพื่อนำไปใช้อีกครั้งภายหลังได้

อธิบายง่ายๆโดยตัวอย่าง ดังนี้

sed 's/123/123 123/g' test.txt

ตัวอย่างนี้ จะทำการ copy ทำซ้ำตัวเอง โดยถ้า sed เจอ pattern ที่เหมือนกับ 123 ก็จะทำการแทนที่โดยเขียนตัวเองสองรอบ

เช่น ถ้าไฟล์ข้อความเป็น
123 abc

ผลลัพธ์ก็จะได้
123 123 abc
ก็ดูเหมือนจะดี แต่ถ้าตัวเลขที่ต้องการจะทำซ้ำนั้นไม่ได่มีแค่รูปแบบเดียว เช่น

123 abc
456 gef
789 tgh

ซึ่งผลลัพธ์ที่ต้องการ คือต้องการให้ SED พิมพ์ข้อมูลตัวเลขซ้ำสองครั้ง

ถ้าไม่ใช้ function เสริมใน SED แล้วล่ะก็

เราก็ต้องพิมพ์คำสั่งที่ยาวเหยียดเฉียดเมตร

มาถึงจุดนี้ Regular Expression จะเริ่มเข้ามามีบทบาท ทำให้ชีวิตเราง่ายขึ้น(มาก)
โดยเราจะใช้ RegExp เพื่อทำ pattern ที่จะใช้ในการ Match ถ้าพบว่า pattern ตรงกับ RegExp ก็จะเริ่มทำงานทันที

แต่ในเวลาที่จะแสดงผล เราไม่สามารถบอกให้แสดงผลด้วย RegExp ได้ เพราะ software จะไม่เข้าใจว่าเราต้องการแสดงอะไร
จึงต้องใช้ สัญลักษณ์ในการแทนสิ่งที่ตรงกับ RegExp ซึ่งใน SED จะใช้ & ในการแสดงผล

sed 's/[0-9]*/& &/g' test.txt
sed 's/[0-9][0-9]*/& &/g' test.txt

แค่นี้ ชีวิตก็ง่ายขึ้น