sed
API ของดั้งเดิมคือ - และนี่คือโดยการออกแบบ อย่างน้อยที่สุดมันก็ยังคงเป็นแบบดั้งเดิมโดยการออกแบบ - ไม่ว่ามันจะถูกออกแบบมาตั้งแต่แรกเริ่มฉันไม่สามารถพูดได้ ในกรณีส่วนใหญ่การเขียนsed
สคริปต์ซึ่งเมื่อเรียกใช้จะส่งออกสคริปต์อื่นsed
เป็นเรื่องง่ายแน่นอน sed
มากมักจะนำไปใช้ในลักษณะนี้โดย preprocessors แมโครเช่นและm4
/ หรือmake
(สิ่งต่อไปนี้เป็นกรณีการใช้งานสมมุติอย่างสูง: มันเป็นปัญหาที่ได้รับการออกแบบมาเพื่อให้เหมาะกับการแก้ปัญหาหากรู้สึกว่ายืดออกไปกับคุณนั่นอาจเป็นเพราะมันเป็นเช่นนั้น
พิจารณาไฟล์อินพุตต่อไปนี้:
cat <<"" >./infile
camel
cat dog camel
dog cat
switch
upper
lower
ถ้าเราอยากจะเขียนsed
สคริปต์ซึ่งจะผนวกคำ-caseถึงหางของแต่ละเหมาะสมคำในแฟ้มใส่ข้างต้น แต่ถ้ามันอาจจะพบได้ในบรรทัดในบริบทที่เหมาะสมและเราต้องการที่จะทำเช่นนั้นได้อย่างมีประสิทธิภาพที่สุด( อย่างที่ควรจะเป็นเป้าหมายของเราเช่นในระหว่างการดำเนินการคอมไพล์)จากนั้นเราควรหลีกเลี่ยงการใช้/
regexp /
มากที่สุด
สิ่งหนึ่งที่เราอาจทำคือแก้ไขไฟล์ล่วงหน้าในระบบของเราทันทีและไม่ต้องโทรsed
เลยระหว่างการรวบรวม แต่ถ้าคำใดคำหนึ่งในไฟล์ควรหรือไม่ควรรวมอยู่บนพื้นฐานของการตั้งค่าท้องถิ่นและ / หรือตัวเลือกเวลาคอมไพล์ดังนั้นการทำเช่นนั้นน่าจะไม่ใช่ทางเลือกที่ต้องการ
สิ่งที่เราจะทำก็คือการประมวลผลไฟล์ที่ตอนนี้กับ regexps เราสามารถสร้าง - และรวมไว้ในการคอมไพล์ของเรา - sed
สคริปต์ที่สามารถใช้การแก้ไขตามหมายเลขบรรทัด - ซึ่งโดยทั่วไปแล้วเป็นเส้นทางที่มีประสิทธิภาพมากขึ้นในระยะยาว
ตัวอย่างเช่น:
n=$(printf '\\\n\t')
grep -En 'camel|upper|lower' <infile |
sed " 1i${n%?}#!/usr/heirloom/bin/posix2001/sed -nf
s/[^:]*/:&$n&!n;&!b&$n&/;s/://2;\$a${n%?}q"'
s/ *cat/!/g;s/ *dog/!/g
s| *\([cul][^ ]*\).*|s/.*/\1-case/p|'
... ซึ่งเขียนเอาต์พุตในรูปแบบของsed
สคริปต์และดูเหมือน ...
#!/usr/heirloom/bin/posix2001/sed -nf
:1
1!n;1!b1
1s/.*/camel-case/p
:2
2!n;2!b2
2!!s/.*/camel-case/p
:5
5!n;5!b5
5s/.*/upper-case/p
:6
6!n;6!b6
6s/.*/lower-case/p
q
เมื่อเอาต์พุตนั้นถูกบันทึกลงในไฟล์ข้อความที่รันได้บนเครื่องของฉันที่ชื่อ./bang.sed
และรันเหมือน./bang.sed ./infile
เอาต์พุตคือ:
camel-case
upper-case
lower-case
ตอนนี้คุณอาจถามฉัน ... ทำไมฉันต้องทำอย่างนั้น? ทำไมฉันถึงไม่ยึดเหนี่ยวgrep
แมตช์? ใครใช้อูฐเคสด้วยล่ะ และสำหรับคำถามแต่ละข้อที่ฉันสามารถตอบได้เท่านั้นฉันไม่มีความคิด ...เพราะฉันไม่มี ก่อนที่จะอ่านคำถามนี้ฉันไม่เคยสังเกตเห็นmulti-! การแยกความต้องการในสเป็ค - ฉันคิดว่ามันเป็นระเบียบสวย
หลาย! สิ่งที่ไม่ได้ทันทีทำให้รู้สึกถึงฉันแม้ว่า - มากของsed
สเปคจะมุ่งเน้นเพียงแค่แยกกันและเพียงแค่สร้าง sed
สคริปต์ คุณอาจพบว่า\n
ตัวคั่น ewline ที่จำเป็นสำหรับการ[wr:bt{]
ทำความเข้าใจให้มากขึ้นในบริบทนั้นและหากคุณคำนึงถึงความคิดนั้นคุณอาจเข้าใจถึงแง่มุมอื่น ๆ ของข้อมูลจำเพาะได้ดีขึ้น(เช่น:
ไม่ยอมรับที่อยู่และq
ปฏิเสธที่จะ ยอมรับใด ๆ เพิ่มเติมกว่า 1)
ในตัวอย่างข้างต้นที่ผมเขียนออกมาเป็นรูปแบบหนึ่งของsed
สคริปต์ซึ่งสามารถที่เคยอ่านครั้งเดียว หากคุณมองมันอย่างหนักคุณอาจสังเกตเห็นว่าเมื่อsed
อ่านไฟล์แก้ไขมันจะดำเนินต่อจากบล็อกคำสั่งหนึ่งไปยังบล็อกถัดไป - มันจะไม่แยกออกจากหรือแก้ไขสคริปต์ของมันจนกว่ามันจะผ่านไฟล์แก้ไข
ฉันคิดว่าหลาย! ที่อยู่อาจมีประโยชน์มากกว่าในบริบทนั้นมากกว่าในที่อื่นบางแห่ง แต่โดยความจริงแล้วฉันไม่สามารถนึกถึงกรณีใดกรณีหนึ่งที่ฉันใช้เพื่อการใช้งานที่ดีsed
มาก ผมยังคิดว่ามันน่าสังเกตว่า GNU / BSD sed
s ทั้งล้มเหลวในการจัดการกับมันตามที่ระบุไว้ - นี้อาจจะไม่เป็นลักษณะของสเปคที่อยู่ในความต้องการมากและดังนั้นหากการดำเนินการมองเห็นมันฉันสงสัยอย่างจริงจังมากข้อบกพร่อง @กล่องจะประสบ ผลก็คือชะมัด
ที่กล่าวว่าความล้มเหลวในการจัดการสิ่งนี้ตามที่ระบุไว้เป็นข้อผิดพลาดสำหรับการใช้งานที่อ้างว่าเป็นไปตามข้อกำหนดดังนั้นฉันจึงคิดว่าการส่งอีเมลไปยังกล่อง dev ที่เกี่ยวข้องนั้นถูกเรียก - ที่นี่และฉันตั้งใจจะทำเช่นนั้น
!
ทำหน้าที่เป็นตัวสลับ,/pattern/!!
เป็นเช่นเดียวกับ/pattern/
และเป็นเช่นเดียวกับ/pattern/!!!
/pattern/!
ใน FreeBSD หลาย ๆ ตัว!
จะเหมือนกับตัวเดียว