คอมพิวเตอร์ หน้าต่าง อินเทอร์เน็ต

ตัวอย่าง sed ของ Linux การเรียนรู้คำสั่ง Linux: sed สรุปโปรแกรม sed

การแนะนำ

คำสั่ง sed คือ Stream EDitor สำหรับการแก้ไขข้อความอัตโนมัติ "ตัวแก้ไขสตรีม" - ในแง่ที่ว่าสามารถแก้ไขสตรีมข้อมูลขาเข้าได้อย่างต่อเนื่อง เช่น เป็นส่วนหนึ่งของช่องทางโปรแกรม (ไปป์) โดยอัตโนมัติ - หมายความว่าทันทีที่คุณตั้งกฎการแก้ไข ส่วนที่เหลือจะเกิดขึ้นโดยที่คุณไม่ต้องมีส่วนร่วมที่น่าเบื่อ กล่าวอีกนัยหนึ่ง เอดิเตอร์ sed ไม่มีการโต้ตอบ

โปรแกรม sed นั้นซับซ้อนกว่าคำสั่งที่เราได้พูดคุยไปแล้วในบทความก่อนหน้าในชุด HuMan มันมีคลังแสงของคำสั่งของตัวเอง ดังนั้นเพื่อหลีกเลี่ยงการพูดซ้ำซากและความสับสน ในบทความนี้ คำสั่ง sed ต่อจากนี้ไปจะเรียกว่า "โปรแกรม" หรือ "ตัวแก้ไข" และคำสั่งของตัวแก้ไข sed จะเรียกง่ายๆว่าคำสั่ง

โปรแกรม sed สามารถทำงานที่ซับซ้อนได้ และต้องใช้เวลาในการเรียนรู้วิธีกำหนดงานเหล่านี้

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

เราจะเริ่มจากง่ายไปซับซ้อน เพื่อให้คุณสามารถคิดได้ว่าจะหยุดตรงไหนเสมอ

คำสั่ง s - การทดแทน (การแทนที่)

โปรแกรม sed มีคำสั่งมากมายในตัวมันเอง ผู้ใช้ส่วนใหญ่รู้แค่คำสั่ง s เท่านั้น และนี่ก็เพียงพอแล้วที่จะทำงานกับโปรแกรมแก้ไข sed คำสั่ง s แทนที่ PATTERN ด้วย REPLACE:

sed s/ตัวอย่าง/การเปลี่ยน/

$ สะท้อนวัน | sed s/วัน/คืน/ (ป้อน) คืน

มันไม่ง่ายไปกว่านี้อีกแล้ว และนี่คือตัวอย่างอินพุตจากไฟล์ zar.txt:

ในตอนเช้าเขาออกกำลังกาย ฟ้าผ่าเป็นประจุไฟฟ้า $ sed s/charge/discharge/ zar.txt ในตอนเช้าเขาออกจากโรงพยาบาล ฟ้าผ่าคือการคายประจุไฟฟ้า

ฉันไม่ได้ใส่ s/SAMPLE/REPLACE/ ในเครื่องหมายคำพูดเพราะตัวอย่างนี้ไม่ต้องการเครื่องหมายคำพูด แต่หากมีอักขระเมตา ก็จำเป็นต้องมีเครื่องหมายคำพูด เพื่อไม่ให้หัวของคุณแตกทุกครั้งและไม่ให้ทำผิดพลาดโดยไม่ได้ตั้งใจให้ใส่เครื่องหมายคำพูดเสมอโดยเฉพาะเครื่องหมายที่ "แข็งแกร่งกว่า" นี่เป็นนิสัยที่ดี คุณไม่สามารถทำให้โจ๊กเสียด้วยน้ำมันได้ ฉันก็จะไม่ข้ามเครื่องหมายคำพูดในตัวอย่างที่ตามมาทั้งหมดเช่นกัน

ดังที่เราเห็น คำสั่งทดแทนมีองค์ประกอบสี่ส่วน:

S คำสั่งนั้นเอง /.../.../ ตัวคั่นรูปแบบ PATTERN สำหรับการค้นหาและการแทนที่นิพจน์ REPLACE ที่จะแทนที่ PATTERN หากพบ

เครื่องหมายทับ (/) ถูกใช้เป็นตัวคั่นตามธรรมเนียม เนื่องจากบรรพบุรุษของ sed ซึ่งเป็นเอดิเตอร์ ed ใช้เครื่องหมายเหล่านี้ (เช่นเดียวกับเอดิเตอร์ vi) ในบางกรณี ตัวคั่นดังกล่าวไม่สะดวกอย่างยิ่ง เช่น เมื่อคุณต้องการเปลี่ยนพาธไปยังไดเร็กทอรีที่มีเครื่องหมายทับ (/usr/local/bin) ในกรณีนี้ คุณต้องแยกเครื่องหมายทับไปข้างหน้าด้วยเครื่องหมายแบ็กสแลช:

Sed "s/\/usr\/local\/bin/\/common\/bin/"

สิ่งนี้เรียกว่า "รั้วล้อมรั้ว" และดูน่าเกลียดมากและที่สำคัญที่สุดคือเข้าใจยาก

สิ่งพิเศษเกี่ยวกับ sed คือมันช่วยให้คุณใช้ตัวคั่นใดๆ ได้ เช่น ขีดล่าง:

$ สะท้อนวัน | เซดs_day_night_คืน

หรือลำไส้ใหญ่:

$ สะท้อนวัน | sed s:วัน:คืน:คืน

ขณะค้นหาตัวคั่นที่คุณต้องการ หากได้รับข้อความว่า "incomplete `s command" แสดงว่าอักขระตัวนี้ไม่ใช่ตัวคั่นที่ดี หรือคุณลืมใส่ตัวคั่นหนึ่งหรือสองตัว

ในบทความนี้ ฉันต้องใช้ตัวคั่นแบบเดิม (/) เพื่อหลีกเลี่ยงไม่ให้ผู้อ่านสับสน แต่ถ้าจำเป็น ฉันจะใช้เครื่องหมายตัวหนอน (~) เป็นตัวคั่น

นิพจน์ทั่วไป (RE)

(นิพจน์ทั่วไป, regexp, RE)

หัวข้อของนิพจน์ทั่วไปมีมากมายจนอุทิศให้กับหนังสือทั้งเล่ม (ดูลิงก์ท้ายบทความ) อย่างไรก็ตาม การพูดคุยอย่างจริงจังเกี่ยวกับ sed editor โดยไม่ใช้นิพจน์ทั่วไปนั้นให้ผลไม่ดีเท่ากับการพูดถึงตรีโกณมิติโดยใช้การเพิ่มแท่ง ดังนั้นจึงจำเป็นต้องพูดถึงนิพจน์ทั่วไปที่มักใช้กับโปรแกรม sed เป็นอย่างน้อย

กับหรือจดหมายอื่นๆ ตัวอักษร ตัวเลข และอักขระที่ไม่ใช่อักขระพิเศษอื่นๆ ส่วนใหญ่ถือเป็นนิพจน์ทั่วไปที่แสดงถึงตัวมันเอง

* เครื่องหมายดอกจันที่ตามหลังสัญลักษณ์หรือนิพจน์ทั่วไปหมายถึงตัวเลขใดๆ (รวมถึงศูนย์) ที่ซ้ำกันของสัญลักษณ์นี้หรือนิพจน์ทั่วไป

\+ ระบุการซ้ำกันของอักขระหรือนิพจน์ทั่วไปหนึ่งรายการหรือมากกว่า

\? หมายถึงไม่มีหรือซ้ำหนึ่งครั้ง

\(ฉัน\)หมายความว่าฉันทำซ้ำอย่างแน่นอน

\(ฉัน,เจ\)จำนวนการทำซ้ำอยู่ในช่วงตั้งแต่ i ถึง j

\(ฉัน,\)จำนวนการซ้ำมากกว่าหรือเท่ากับ i

\(,เจ\) จำนวนการซ้ำน้อยกว่าหรือเท่ากับ j

\(อีกครั้ง\) จำนิพจน์ทั่วไปหรือบางส่วนไว้เพื่อใช้โดยรวมในอนาคต ตัวอย่างเช่น \(a-z\)* จะค้นหาการรวมกันของตัวเลขใดๆ (รวมถึงศูนย์) ตัวอักษรพิมพ์เล็ก

. จับคู่อักขระใดๆ รวมถึงการขึ้นบรรทัดใหม่

^ บ่งชี้นิพจน์ที่เป็นโมฆะที่จุดเริ่มต้นของบรรทัด กล่าวอีกนัยหนึ่ง สิ่งใดก็ตามที่นำหน้าด้วยเครื่องหมายนี้จะต้องปรากฏที่ต้นบรรทัด ตัวอย่างเช่น ^#include จะค้นหาบรรทัดที่ขึ้นต้นด้วย #include

$ เช่นเดียวกับอันก่อนหน้าใช้เฉพาะกับท้ายบรรทัดเท่านั้น

[รายการ]หมายถึงอักขระใดๆ จาก LIST ตัวอย่างเช่น มันจะค้นหาตัวอักษรสระภาษาอังกฤษ

[^รายการ]หมายถึงอักขระใดๆ ยกเว้นที่อยู่ในรายการ ตัวอย่างเช่น [^aeiou] จะค้นหาพยัญชนะใดก็ได้ หมายเหตุ: LIST อาจเป็นช่วงเวลาได้ เช่น [a-z] ซึ่งจะหมายถึงอักษรตัวพิมพ์เล็ก หากคุณต้องการรวม ] (วงเล็บเหลี่ยม) ไว้ใน LIST ให้ระบุก่อนในรายการ หากคุณต้องการรวม - (ยัติภังค์) ในรายการ ให้ระบุเป็นรายการแรกหรือรายการสุดท้าย

RE1\|RE2หมายถึง PB1 หรือ PB2

RE1RE2หมายถึงการรวมกันของนิพจน์ทั่วไป РВ1 และ РВ2

\nระบุอักขระขึ้นบรรทัดใหม่

\$; \*; \.; \[; \\; \^ หมายความว่าตาม: $; *; .; [; \; ^

ความสนใจ: sed ไม่รองรับแบ็กสแลช (\) ที่เหลือของภาษา C

\1 \2 \3 \4 \5 \6 \7 \8 \9 ระบุส่วนที่ตรงกันของนิพจน์ทั่วไป โดยจัดเก็บโดยใช้เครื่องหมาย \(และ \)

ตัวอย่างบางส่วน:

เอบีซีดีเอฟแปลว่า abcdef

ก*ขแทนศูนย์หรือจำนวนใดๆ ของ a และ b หนึ่งตัว ตัวอย่างเช่น aaaaaaab; ab; หรือข

ก\?ขหมายถึง b หรือ ab

ก\+ข\+แทน a's หนึ่งตัวหรือมากกว่า และ b's หนึ่งตัวหรือมากกว่า ตัวอย่างเช่น: ab; อ๊าาา; แอ๊บแบ๊บ; หรืออร๊ายยยยย

.* หมายถึงอักขระทุกตัวในบรรทัด ทุกบรรทัด รวมถึงอักขระว่างด้วย

.\+ จับคู่อักขระทั้งหมดบนบรรทัด แต่เฉพาะในบรรทัดที่มีอักขระอย่างน้อยหนึ่งตัวเท่านั้น สตริงว่างไม่ตรงกับนิพจน์ทั่วไปนี้

^main.*(.*)โดยจะค้นหาบรรทัดที่ขึ้นต้นด้วยคำว่า main และมีวงเล็บเปิดและปิดด้วย และอาจมีอักขระกี่ตัวก็ได้ก่อนและหลังวงเล็บเปิด (หรืออาจไม่มีก็ได้)

^# จะค้นหาบรรทัดที่ขึ้นต้นด้วยเครื่องหมาย # (เช่น ความคิดเห็น)

\\$ จะค้นหาบรรทัดที่ลงท้ายด้วยแบ็กสแลช (\)

ตัวอักษรหรือตัวเลขใดๆ

[^ ]\+ (วงเล็บเหลี่ยม นอกเหนือจากสัญลักษณ์ ^ แล้ว ยังมีช่องว่างและแท็บด้วย) -- หมายถึงอักขระหนึ่งตัวหรือจำนวนเท่าใดก็ได้ ยกเว้นช่องว่างและแท็บ โดยปกติแล้วนี่จะหมายถึงคำ

^.*ก.*$ระบุตัวพิมพ์ใหญ่ A ตรงกลางบรรทัด

อ.\(9\)$ระบุอักษรตัวใหญ่ A ซึ่งเป็นอักษรตัวที่สิบนับจากท้ายบรรทัดพอดี

^.\(,15\)กระบุอักษรตัวใหญ่ A ซึ่งตรงกับตัวที่สิบหกจากจุดเริ่มต้นของบรรทัด

ตอนนี้เราได้เห็นนิพจน์ทั่วไปแล้ว เรากลับมาที่คำสั่ง s ใน sed กัน

การใช้สัญลักษณ์ & เมื่อไม่ทราบรูปแบบ “ไม่ทราบได้อย่างไร” คุณถามว่า “คุณไม่รู้ว่าต้องการแทนที่อะไร” ฉันจะตอบ: ฉันต้องการใส่ตัวเลขที่พบในข้อความในวงเล็บ ทำอย่างไร? คำตอบ: ใช้สัญลักษณ์ &

สัญลักษณ์ & (เครื่องหมายและ) เมื่อวางไว้เป็นส่วนหนึ่งของ REPLACEMENT หมายถึงรูปแบบใดๆ ที่พบในข้อความ ตัวอย่างเช่น:

$ เสียงสะท้อน 1234 | sed "s/*/(&)/" (1234)

จำเป็นต้องใช้เครื่องหมายดอกจัน (เครื่องหมายดอกจัน) หลังช่วงเวลาเพื่อแทนที่ตัวเลขทั้งหมดที่พบในตัวอย่าง หากไม่มีมันก็คงจะเป็น:

$ เสียงสะท้อน 1234 | sed "s//(&)/" (1)234

นั่นคือตัวเลขตัวแรกที่พบนั้นถูกนำมาเป็นตัวอย่าง

นี่คือตัวอย่างที่มีการโหลดที่มีความหมายโดยสมบูรณ์: มาสร้างไฟล์ Formula.txt กัน:

A+432-10=น

และใช้คำสั่งกับมัน:

$ sed "s/*-*/(&)/" Formula.txt a+(432-10)=n

สูตรทางคณิตศาสตร์ได้รับความหมายที่ชัดเจน

สัญลักษณ์เครื่องหมายและอีกตัวหนึ่งสามารถใช้เพื่อเพิ่ม PATTERN เป็นสองเท่า:

$ เสียงสะท้อน 123 | sed "s/*/& &/" 123 123

มีความละเอียดอ่อนอย่างหนึ่งที่นี่ หากเราทำให้ตัวอย่างซับซ้อนขึ้นอีกเล็กน้อย:

$ echo "123 abc" | sed "s/*/& &/" 123 123 abc

อย่างที่คุณคาดหวัง เฉพาะตัวเลขเท่านั้นที่จะเพิ่มเป็นสองเท่าเนื่องจากไม่มีตัวอักษรในรูปแบบ แต่ถ้าเราสลับบางส่วนของข้อความ:

$ echo "abc 123" | sed "s/*/& &/" abc 123

ดังนั้นการคูณตัวเลขจะไม่ได้ผล นี่คือคุณลักษณะของนิพจน์ทั่วไป * - จับคู่เฉพาะอักขระตัวแรกของสตริงเท่านั้น หากเราต้องการเพิ่มเลขสองหลักไม่ว่าจะอยู่ที่ใดก็ตาม เราจำเป็นต้องแก้ไขนิพจน์ทั่วไปใน REPLACE:

$ echo "abc defg 123" | sed "s/*/& &/" abc defg 123 123

จากนั้นตัวเลขจะเพิ่มเป็นสองเท่าโดยไม่คำนึงถึงจำนวน "คำ" ก่อนหน้า

การใช้วงเล็บหลีก \(, \) และ \1 เพื่อประมวลผลส่วนหนึ่งของรูปแบบ วงเล็บหลีก \(และ \) ใช้เพื่อจัดเก็บส่วนหนึ่งของนิพจน์ทั่วไป

สัญลักษณ์ \1 หมายถึงส่วนแรกที่จดจำไว้ \2 หมายถึงส่วนที่สอง และอื่นๆ มากถึงเก้าส่วนที่จำได้ (โปรแกรมไม่รองรับมากกว่านี้) ลองดูตัวอย่าง:

$ echo abcd123 | sed "s/\(*\).*/\1/" abcd

ในที่นี้ \(*\) หมายความว่าโปรแกรมจะต้องจำอักขระตัวอักษรทั้งหมดไม่ว่าจำนวนเท่าใดก็ได้ .* หมายถึงจำนวนอักขระเท่าใดก็ได้หลังจากส่วนแรกที่จำได้ และ \1 หมายความว่าเราต้องการเห็นเพียงส่วนแรกที่จำได้เท่านั้น ถูกต้อง: ในเอาต์พุตของโปรแกรมเราจะเห็นเฉพาะตัวอักษรและไม่มีตัวเลข

ในการสลับคำ คุณต้องจำรูปแบบย่อยสองแบบ แล้วจึงสลับ:

$ echo เพนกวินโง่ |sed "s/\([a-z]*\) \([a-z]*\)/\2 \1/" เพนกวินโง่

โดยที่ \2 หมายถึงรูปแบบย่อยที่สอง และ \1 หมายถึงรูปแบบย่อยแรก สังเกตระยะห่างระหว่างนิพจน์แรก \([a-z]*\) และนิพจน์ที่สอง \([a-z]*\) จำเป็นต้องค้นหาคำสองคำ

เครื่องหมาย \1 ไม่จำเป็นต้องปรากฏเฉพาะใน REPLACEMENT เท่านั้น แต่ยังสามารถปรากฏใน SAMPLE ได้ เช่น เมื่อเราต้องการลบคำที่ซ้ำกัน:

$ echo นกเพนกวิน นกเพนกวิน | sed "s/\([a-z]*\) \1/\1/" เพนกวิน

ตัวดัดแปลงการทดแทนคำสั่ง

ตัวแก้ไขการแทนที่จะถูกวางไว้หลังตัวคั่นสุดท้าย โมดิฟายเออร์เหล่านี้จะกำหนดว่าโปรแกรมจะทำอะไรหากมีการจับคู่ PATTERN ในสตริงมากกว่าหนึ่งรายการ และวิธีการแทนที่

ตัวแก้ไข /g

การทดแทนระดับโลก

โปรแกรม sed เช่นเดียวกับยูทิลิตี้ Unix ส่วนใหญ่ จะอ่านทีละบรรทัดเมื่อทำงานกับไฟล์ ถ้าเราสั่งให้แทนที่คำใด ๆ โปรแกรมจะแทนที่เฉพาะคำแรกที่ตรงกับ PATTERN ในบรรทัดที่กำหนด หากเราต้องการเปลี่ยนทุกคำที่ตรงกับรูปแบบ เราควรป้อนตัวแก้ไข /g

หากไม่มีตัวแก้ไข /g:

$ echo แมวตัวนี้เป็นแมวที่ธรรมดาที่สุด | sed "s/cat/kitten/" ลูกแมวตัวนี้เป็นแมวที่ธรรมดาที่สุด

ผู้แก้ไขจะแทนที่เฉพาะคำแรกที่ตรงกันเท่านั้น

และตอนนี้มีตัวแก้ไขการแทนที่ทั่วโลก:

$ echo แมวตัวนี้เป็นแมวที่ธรรมดาที่สุด | sed "s/cat/kitten/g" ลูกแมวตัวนี้เป็นลูกแมวที่ธรรมดาที่สุด

การแข่งขันทั้งหมดในสตริงนี้ได้ถูกแทนที่แล้ว

และถ้าคุณต้องการเปลี่ยนคำทั้งหมดให้ใส่ในวงเล็บ? จากนั้นสำนวนปกติจะกลับมาช่วยเหลืออีกครั้ง หากต้องการเลือกอักขระตัวอักษรทั้งหมดทั้งตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก คุณสามารถใช้โครงสร้าง [A-Ya-Ya] ได้ แต่จะไม่รวมคำเช่น "something" หรือ "s"ezd" โครงสร้าง [^] มีมากกว่านั้นมาก สะดวก ]* ซึ่งตรงกับอักขระทั้งหมดยกเว้นช่องว่าง ดังนั้น:

$ สะท้อนนกเพนกวินโง่ ๆ ซ่อนตัวอย่างขี้อาย | sed "s/[^ ]*/(&)/g" (โง่) (เพนกวิน) (ขี้อาย) (ซ่อน)

วิธีการเลือกแมตช์ที่เหมาะสมจากหลาย ๆ อย่าง

หากคุณไม่ใช้ตัวดัดแปลง โปรแกรม sed จะแทนที่เฉพาะคำแรกที่ตรงกับ PATTERN หากคุณใช้โมดิฟายเออร์ /g โปรแกรมจะแทนที่ทุกคำที่ตรงกัน คุณจะเลือกหนึ่งการแข่งขันได้อย่างไรหากมีหลายรายการอยู่ในบรรทัด? - การใช้สัญลักษณ์ทั่วไป \(และ \) ที่เราคุ้นเคยอยู่แล้ว จำตัวอย่างย่อย และเลือกสัญลักษณ์ที่คุณต้องการโดยใช้สัญลักษณ์ \1 - \9

$ echo เพนกวินโง่ | sed "s/\([a-z]*\) \([a-z]*\)/\2 /" เพนกวิน

ในตัวอย่างนี้ เราจำทั้งสองคำได้ และนำคำที่สอง (เพนกวิน) มาเป็นอันดับแรก ลบคำแรก (โง่) ออกโดยการเว้นวรรคในส่วน REPLACEMENT ถ้าเราแทนที่ช่องว่างด้วยคำ มันจะแทนที่คำแรก (โง่):

$ echo เพนกวินโง่ | sed "s/\([a-z]*\) \([a-z]*\)/\2 smart /" เพนกวินอัจฉริยะ

ตัวแก้ไขตัวเลข

นี่คือตัวเลขหนึ่ง/สอง/สามหลักที่วางอยู่หลังตัวคั่นสุดท้าย และระบุว่าจะต้องแทนที่คู่ใด

$ echo เพนกวินโง่มาก | sed "s/[a-z]*/good/2" นกเพนกวินที่ดีมาก

ในตัวอย่างนี้ แต่ละคำตรงกัน และเราได้แจ้งให้บรรณาธิการทราบว่าคำใดที่เราต้องการแทนที่ด้วยการวางตัวแก้ไข 2 หลังส่วน REPLACE

คุณสามารถรวมตัวแก้ไขตัวเลขกับตัวแก้ไข /g ได้ หากคุณต้องการปล่อยให้คำแรกไม่เปลี่ยนแปลงและแทนที่คำที่สองและคำถัดไปด้วยคำว่า "(ลบ)" คำสั่งจะเป็นดังนี้:

$ echo เพนกวินโง่มาก | sed "s/[a-z]*/(ลบแล้ว)/2g" มาก (ลบแล้ว) (ลบแล้ว)

หากคุณต้องการลบการจับคู่ที่ตามมาทั้งหมดยกเว้นรายการแรก คุณควรเว้นวรรคในส่วน REPLACE:

$ echo เพนกวินโง่มาก | sed "s/[a-z]*/ /2g" มาก

หรือไม่ใส่อะไรเลย:

$ echo เพนกวินโง่มาก | sed "s/[^ ]*//2g" ดีมาก

ตัวแก้ไขตัวเลขอาจเป็นจำนวนเต็มใดก็ได้ตั้งแต่ 1 ถึง 512 ตัวอย่างเช่น หากคุณต้องการใส่โคลอนหลังอักขระตัวที่ 80 ของแต่ละบรรทัด คำสั่งจะช่วย:

$sed ชื่อไฟล์ "s/./&:/80"

Modifier /p - ส่งออกไปยังเอาต์พุตมาตรฐาน (พิมพ์)

โปรแกรม sed ส่งออกผลลัพธ์ไปยังเอาต์พุตมาตรฐาน (เช่น หน้าจอมอนิเตอร์) ตามค่าเริ่มต้นแล้ว ตัวแก้ไขนี้ใช้กับตัวเลือก sed -n เท่านั้น ซึ่งเพิ่งบล็อกเอาต์พุตของผลลัพธ์ไปยังหน้าจอ

ตัวแก้ไข /w

ช่วยให้คุณเขียนผลลัพธ์ของการประมวลผลข้อความไปยังไฟล์ที่ระบุ:

$ sed "s/SAMPLE/REPLACE/w ชื่อไฟล์

/e ตัวแก้ไข (ส่วนขยาย GNU)

อนุญาตให้คุณระบุคำสั่งเชลล์ (ไม่ใช่โปรแกรม sed) เป็นการแทนที่ หากพบการจับคู่กับ PATTERN มันจะถูกแทนที่ด้วยเอาต์พุตของคำสั่งที่ระบุในส่วน REPLACE ตัวอย่าง:

$ echo คืน | sed "s/night/echo day/e" วัน

ตัวดัดแปลง /I และ /i (ส่วนขยาย GNU)

ทำให้กระบวนการเปลี่ยนไม่คำนึงถึงขนาดตัวพิมพ์

$ echo ไนท์ | sed "s/คืน/วัน/i" วัน

ชุดค่าผสมตัวแก้ไข

ตัวแก้ไขสามารถนำมารวมกันได้เมื่อเหมาะสม ในกรณีนี้ ควรวางตัวดัดแปลง w ไว้ท้ายสุด

อนุสัญญา (ส่วนขยาย GNU) มีเพียงห้าเท่านั้น:

\ลแปลงอักขระ REPLACE เป็นตัวพิมพ์เล็ก \ลแปลงอักขระ REPLACE ถัดไปเป็นตัวพิมพ์เล็ก \ยูแปลงอักขระ REPLACE เป็นตัวพิมพ์ใหญ่ \ยูแปลงอักขระ REPLACE ถัดไปเป็นตัวพิมพ์ใหญ่ \Eเลิกทำการแปลที่เริ่มโดย \L หรือ \U ด้วยเหตุผลที่ชัดเจน จึงมีการใช้แบบแผนเหล่านี้เพียงอย่างเดียว ตัวอย่างเช่น:

$ echo เพนกวินโง่ | sed "s/stupid/\u&/" นกเพนกวินโง่

$ echo ลูกหมาน้อย | sed "s/[a-z]*/\u&/2" ลูกสุนัขตัวน้อย

เราได้ครอบคลุมเกือบทุกแง่มุมของคำสั่ง sed ถึงเวลาดูตัวเลือกของโปรแกรมนี้แล้ว

ตัวเลือกโปรแกรม sed

โปรแกรมนี้มีตัวเลือกน้อยจนน่าประหลาดใจ (ซึ่งค่อนข้างจะชดเชยส่วนเกินของคำสั่ง, ตัวดัดแปลง และฟังก์ชันอื่นๆ) นอกจากตัวเลือกที่รู้จักกันดี --help (-h) และ --version (-V) ซึ่งเราจะไม่พิจารณาแล้ว มีเพียงสามตัวเลือกเท่านั้น:

ตัวเลือก -e--expression=command_set

วิธีหนึ่งในการดำเนินการหลายคำสั่งคือการใช้ตัวเลือก -e ตัวอย่างเช่น:

Sed -e "s/a/A/" -e "s/b/B/" ชื่อไฟล์

ตัวอย่างก่อนหน้านี้ทั้งหมดในบทความนี้ไม่จำเป็นต้องใช้ตัวเลือก -e เพียงเพราะมีคำสั่งเดียว เราสามารถใช้ตัวเลือก -e ในตัวอย่างได้ ซึ่งจะไม่เปลี่ยนแปลงอะไรเลย

ตัวเลือก -ฉหากคุณต้องการดำเนินการคำสั่งจำนวนมาก จะสะดวกกว่าถ้าเขียนคำสั่งลงในไฟล์และใช้ตัวเลือก -f:

Sed -f ชื่อไฟล์ sedscript

Sedscript นี่คือชื่อของไฟล์ที่มีคำสั่ง ไฟล์นี้เรียกว่าสคริปต์โปรแกรม sed (ต่อไปนี้จะเรียกว่าสคริปต์) แต่ละคำสั่งสคริปต์ควรใช้บรรทัดแยกกัน ตัวอย่างเช่น:

# ความคิดเห็น - สคริปต์นี้จะเปลี่ยนสระตัวพิมพ์เล็กทั้งหมดเป็นสระตัวพิมพ์ใหญ่ s/a/A/g s/e/E/g s/i/I/g s/o/O/g s/u/U/g

คุณสามารถตั้งชื่อสคริปต์ตามที่คุณต้องการได้ สิ่งสำคัญคือต้องไม่สับสนระหว่างไฟล์สคริปต์กับไฟล์ที่กำลังประมวลผล

ตัวเลือก -nโปรแกรม sed -n ไม่พิมพ์สิ่งใดไปยังเอาต์พุตมาตรฐาน หากต้องการรับการถอนเงิน คุณต้องมีคำแนะนำพิเศษ เราคุ้นเคยกับโมดิฟายเออร์ /p เรียบร้อยแล้ว ซึ่งสามารถใช้เพื่อบ่งชี้ดังกล่าวได้ จำไฟล์ zar.txt กัน:

$ sed "s/1-9/&/p" zar.txt ในตอนเช้าเขาออกกำลังกาย ฟ้าผ่าเป็นประจุไฟฟ้า

เนื่องจากไม่พบรายการที่ตรงกันกับ PATTERN (ไม่มีตัวเลขในไฟล์) คำสั่ง s พร้อมด้วยโมดิฟายเออร์ /p และเครื่องหมาย & เป็นการแทนที่ (โปรดจำไว้ว่าเครื่องหมายแอมเพอร์แซนด์หมายถึง PATTERN นั่นเอง) จึงทำงานเหมือนกับคำสั่ง cat

หากพบ PATTERN ในไฟล์ บรรทัดที่มี PATTERN จะเพิ่มเป็นสองเท่า:

$ sed "s/exercise/&/p" zar.txt ในตอนเช้าเขาออกกำลังกาย ในตอนเช้าเขาออกกำลังกาย ฟ้าผ่าเป็นประจุไฟฟ้า

ตอนนี้เรามาเพิ่มตัวเลือก -n:

$ sed -n "s/exercise/&/p" zar.txt ในตอนเช้าเขาออกกำลังกาย

ตอนนี้โปรแกรมของเราทำงานเหมือนกับคำสั่ง grep - มันจะส่งคืนเฉพาะบรรทัดที่มี PATTERN เท่านั้น

การเลือกองค์ประกอบที่ต้องการของข้อความที่แก้ไข

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

  • เลือกบรรทัดตามตัวเลข
  • เลือกแถวในช่วงตัวเลขที่กำหนด
  • เลือกเฉพาะแถวที่มีนิพจน์บางอย่าง
  • เลือกเฉพาะบรรทัดระหว่างบางนิพจน์
  • เลือกเฉพาะบรรทัดตั้งแต่ต้นไฟล์จนถึงนิพจน์บางส่วน
  • เลือกเฉพาะบรรทัดจากนิพจน์บางส่วนจนถึงจุดสิ้นสุดของไฟล์

โปรแกรม sed ทำทั้งหมดนี้และอีกมากมาย คำสั่ง sed editor ใดๆ สามารถใช้ตามแอดเดรส ในช่วงของแอดเดรสที่กำหนด หรือภายใต้ข้อจำกัดข้างต้นในช่วงของบรรทัด ที่อยู่หรือข้อจำกัดจะต้องนำหน้าคำสั่งทันที:

Sed "ที่อยู่/คำสั่งจำกัด"

การเลือกแถวตามตัวเลข

นี่เป็นกรณีที่ง่ายที่สุด เพียงระบุจำนวนบรรทัดที่ต้องการก่อนคำสั่ง:

$ sed "4 s/[a-z]*//i" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาดในยามพลบค่ำในยามเช้า ในหิมะที่ละลายในฤดูใบไม้ผลิ ให้กับทุกสิ่งที่พินาศและชาญฉลาด

$ sed "3 s/В/(В)/" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาดในยามพลบค่ำยามเช้า (ใน) หิมะที่ละลายในฤดูใบไม้ผลิ ในทุกสิ่งที่พินาศและชาญฉลาด

การเลือกแถวในช่วงตัวเลข

ไม่น่าแปลกใจเลยที่ช่วงจะถูกระบุโดยคั่นด้วยเครื่องหมายจุลภาค:

$ sed "2.3 s/В/(В)/" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาด (ใน) สนธยายามเช้าตรู่ (ใน) หิมะที่ละลายในฤดูใบไม้ผลิ ในทุกสิ่งที่พินาศและฉลาด

หากคุณต้องการระบุช่วงจนถึงบรรทัดสุดท้ายของไฟล์ แต่คุณไม่รู้ว่ามีกี่บรรทัด ให้ใช้เครื่องหมาย $:

$ sed "2,$ s/in/(in)/i" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาด (ใน) สนธยายามเช้าตรู่ (ใน) หิมะที่ละลายในฤดูใบไม้ผลิ (ใน) ทุกสิ่งที่พินาศและเป็นอยู่ ฉลาด.

การเลือกแถวที่มีนิพจน์

นิพจน์การค้นหาจะอยู่ในเครื่องหมายทับ (/) และวางไว้หน้าคำสั่ง:

$ sed "/morning/ s/in/(in)/i" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาด (ใน) ยามพลบค่ำยามเช้า ในหิมะที่ละลายในฤดูใบไม้ผลิ ในทุกสิ่งที่พินาศและฉลาด

การเลือกแถวในช่วงระหว่างสองนิพจน์

เช่นเดียวกับในกรณีของหมายเลขบรรทัด ช่วงจะถูกระบุโดยคั่นด้วยเครื่องหมายจุลภาค:

$ sed "/morning/,/wise/ s/in/(in)/i" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาด (ใน) สนธยายามเช้าตรู่ (ใน) หิมะละลายในฤดูใบไม้ผลิ (ใน) ทุกอย่าง ที่พินาศและฉลาด

การเลือกบรรทัดจากจุดเริ่มต้นของไฟล์ไปจนถึงนิพจน์ที่ต้องการ

$ sed "1,/snow/ s/in/(in)/i" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาด (ใน) สนธยายามเช้าตรู่ (ใน) หิมะที่ละลายในฤดูใบไม้ผลิในทุกสิ่งที่พินาศและเป็นอยู่ ฉลาด.

การเลือกบรรทัดจากนิพจน์หนึ่งไปยังส่วนท้ายของไฟล์

$ sed "/snow/,$ s/in/(in)/i" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาดในยามพลบค่ำยามเช้า (ใน) หิมะที่ละลายในฤดูใบไม้ผลิ (ใน) ทุกสิ่งที่พินาศและเป็นอยู่ ฉลาด.

คำสั่ง sed editor อื่นๆ

คำสั่ง d (ลบ)

ลบบรรทัดต่อไปนี้ออกจากเอาต์พุตมาตรฐาน:

$ sed "2 d" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาดในหิมะที่ละลายในฤดูใบไม้ผลิในทุกสิ่งที่พินาศและฉลาด

และบ่อยครั้งที่พวกเขาเขียนให้ง่ายขึ้น (ไม่มีช่องว่าง):

Sed "2d" กูมิเลฟ.txt

ทุกสิ่งที่กล่าวไว้ในส่วนที่แล้วเกี่ยวกับการกำหนดแอดเดรสสตริงยังใช้กับคำสั่ง d ด้วย (เช่นเดียวกับคำสั่งเกือบทั้งหมดในตัวแก้ไข sed)

การใช้คำสั่ง d จะสะดวกในการทิ้ง "ส่วนหัว" ที่ไม่จำเป็นของข้อความเมลบางส่วน:

$sed ชื่อไฟล์ "1,/^$/d"

(ลบบรรทัดตั้งแต่บรรทัดแรกถึงบรรทัดว่างบรรทัดแรก)

กำจัดความคิดเห็นในไฟล์กำหนดค่า:

$ sed "/^#/d" /boot/grub/menu.lst

และคุณไม่มีทางรู้ว่าจะต้องลบบรรทัดพิเศษตรงไหน!

คำสั่ง p (พิมพ์)

คำภาษาอังกฤษ "print" แปลว่า "print" ซึ่งในภาษารัสเซียมีความเกี่ยวข้องกับเครื่องพิมพ์หรืออย่างน้อยก็ด้วยแป้นพิมพ์ อันที่จริง คำนี้ในบริบทภาษาอังกฤษมักหมายถึงการส่งออกไปยังหน้าจอมอนิเตอร์ ดังนั้นคำสั่ง p จะไม่พิมพ์อะไรเลย แต่เพียงแสดงบรรทัดที่ระบุ

เมื่อใช้โดยตัวมันเอง คำสั่ง p จะเพิ่มบรรทัดในเอาต์พุตเป็นสองเท่า (ท้ายที่สุดแล้ว โปรแกรม sed จะพิมพ์บรรทัดไปที่หน้าจอตามค่าเริ่มต้น แต่คำสั่ง p จะพิมพ์บรรทัดเดียวกันเป็นครั้งที่สอง)

$ echo ฉันมีแมว | sed "p" ฉันมีแมว ฉันมีแมว

มีการใช้คุณสมบัตินี้ เช่น เพิ่มบรรทัดว่างเป็นสองเท่าเพื่อปรับปรุงรูปลักษณ์ของข้อความ:

$ sed "/^$/ p ชื่อไฟล์

แต่คำสั่ง p จะแสดงสีที่แท้จริงเมื่อใช้ร่วมกับตัวเลือก -n ซึ่งตามที่คุณจำได้ จะป้องกันไม่ให้มีเส้นพิมพ์บนหน้าจอ ด้วยการรวมตัวเลือก -n เข้ากับคำสั่ง p คุณจะได้รับเฉพาะบรรทัดที่ต้องการในเอาต์พุต

ตัวอย่างเช่น ดูที่บรรทัดที่หนึ่งถึงสิบ:

$ sed -n ชื่อไฟล์ "1.10 p"

หรือเพียงแค่แสดงความคิดเห็น:

$ sed -n "/^#/ p" /boot/grub/menu.lst # ไฟล์การกำหนดค่า GRUB "/boot/grub/menu.lst" # สร้างโดย "grubconfig" อาทิตย์ 23 มี.ค. 2551 เวลา 21:45:41 น. # # เริ่มส่วนส่วนกลางของ GRUB # สิ้นสุดส่วนส่วนกลางของ GRUB # การกำหนดค่าพาร์ติชันที่สามารถบูตได้ของ Linux เริ่มต้นขึ้น # การกำหนดค่าพาร์ติชันที่สามารถบูตได้ของ Linux สิ้นสุดลง # การกำหนดค่าพาร์ติชันที่สามารถบูตได้ของ Linux เริ่มต้นขึ้น # การกำหนดค่าพาร์ติชันที่บูตได้ของ Linux สิ้นสุด

สิ่งนี้ชวนให้นึกถึงโปรแกรม grep มาก ซึ่งเราพบแล้วเมื่อเราพูดถึงตัวเลือก -n พร้อมกับโมดิฟายเออร์ /p แต่แตกต่างจากคำสั่ง grep ตัวแก้ไข sed ช่วยให้ไม่เพียงค้นหาบรรทัดเหล่านี้เท่านั้น แต่ยังสามารถเปลี่ยนบรรทัดเหล่านั้นได้ เช่น แทนที่ Linux ทุกที่ด้วย Unix:

$ sed -n "/^#/ p" /boot/grub/menu.lst | sed "s/Linux/Unix/" # ไฟล์การกำหนดค่า GRUB "/boot/grub/menu.lst" # สร้างโดย "grubconfig" อาทิตย์ 23 มี.ค. 2551 เวลา 21:45:41 น. # # เริ่มส่วนส่วนกลางของ GRUB # สิ้นสุดส่วนส่วนกลางของ GRUB # การกำหนดค่าพาร์ติชันที่สามารถบูตได้ของ Unix เริ่มต้นขึ้น # การกำหนดค่าพาร์ติชันที่สามารถบูตได้ของ Unix สิ้นสุดลง # การกำหนดค่าพาร์ติชันที่สามารถบูตได้ของ Unix เริ่มต้นขึ้น # การกำหนดค่าพาร์ติชันที่สามารถบูตได้ของ Unix สิ้นสุดลง

ทีม!

บางครั้งคุณจำเป็นต้องแก้ไขแถวทั้งหมด ยกเว้นแถวที่ตรงกับรูปแบบหรือส่วนที่เลือก อักขระเครื่องหมายอัศเจรีย์ (!) จะกลับรายการที่เลือก ตัวอย่างเช่น ลองลบบรรทัดทั้งหมดยกเว้นบรรทัดที่สองจาก quatrain ของ Gumilyov:

$ sed "2 !d" gumilev.txt ในยามพลบค่ำยามเช้า

หรือเลือกทุกบรรทัด ยกเว้นความคิดเห็น จากไฟล์ /boot/grub/menu.lst:

$ sed -n "/^#/ !p" /boot/grub/menu.lst ค่าเริ่มต้น 1 หมดเวลา 20 gfxmenu (hd0,3)/boot/message title SuSe บนเคอร์เนล root (/dev/hda3) (hd0,2) /boot/vmlinuz root=/dev/hda3 ro vga=773 acpi=off title Linux บน (/dev/hda4) root (hd0,3) เคอร์เนล /boot/vmlinuz root=/dev/hda4 ro vga=0x317

คำสั่ง q (ออก)

คำสั่ง q ยุติโปรแกรม sed หลังจากบรรทัดที่ระบุ วิธีนี้จะสะดวกหากคุณต้องการหยุดแก้ไขหลังจากถึงจุดใดจุดหนึ่งในข้อความ:

$sed ชื่อไฟล์ "11 q"

คำสั่งนี้จะเสร็จสิ้นเมื่อถึงบรรทัดที่ 11

คำสั่ง q เป็นหนึ่งในคำสั่ง sed ไม่กี่คำสั่งที่ไม่ยอมรับช่วงสตริง คำสั่งไม่สามารถหยุดทำงาน 10 ครั้งติดต่อกันได้หากเราป้อน:

Sed "1.10 q" ไร้สาระ!

คำสั่ง w (เขียน)

เช่นเดียวกับโมดิฟายเออร์ w ของคำสั่ง s คำสั่งนี้อนุญาตให้คุณเขียนเอาต์พุตของโปรแกรมลงในไฟล์:

$ sed -n "3,$ w gum.txt" กูมิเลฟ.txt

เราจะได้รับไฟล์ gum.txt ที่มี quatrain ของ Gumilyov สองบรรทัดสุดท้ายจากไฟล์ gumilev.txt ยิ่งไปกว่านั้น หากไฟล์ดังกล่าวมีอยู่แล้ว ไฟล์นั้นจะถูกเขียนทับ หากคุณไม่ป้อนตัวเลือก -n โปรแกรมจะแสดงเนื้อหาทั้งหมดของไฟล์ gumilev.txt นอกเหนือจากการสร้างไฟล์ gum.txt แล้ว

สำหรับการทำงานบนบรรทัดคำสั่ง จะสะดวกกว่าถ้าใช้การเปลี่ยนเส้นทางเอาต์พุตปกติ (> หรือ >>) แต่ในสคริปต์ sed คำสั่ง w อาจจะพบการใช้งานของมัน

คำสั่ง r (อ่าน)

คำสั่งนี้ไม่เพียงแต่อ่านไฟล์ที่ระบุเท่านั้น แต่ยังวางเนื้อหาลงในตำแหน่งที่ต้องการในไฟล์ที่แก้ไขด้วย ในการเลือก "สถานที่ที่เหมาะสม" จะใช้ที่อยู่ที่เราคุ้นเคยอยู่แล้ว (ตามหมายเลขบรรทัดตามสำนวน ฯลฯ ) ตัวอย่าง:

$ echo จากบทกวีของ Gumilyov: | sed "r gumilev.txt"

จากบทกวีของ Gumilyov:

ช่างเป็นความสุขอันน่าประหลาดอย่างยิ่งในเวลาพลบค่ำในยามเช้า ในหิมะที่ละลายในฤดูใบไม้ผลิ ในทุกสิ่งที่พินาศและฉลาด

ทีม=

จะให้หมายเลขบรรทัดที่ระบุ:

$ sed "/snow/=" gumilev.txt ช่างเป็นความสุขที่แปลกประหลาดในยามพลบค่ำยามเช้า 3 ในหิมะที่ละลายในฤดูใบไม้ผลิในทุกสิ่งที่พินาศและฉลาด

$ sed -n "/snow/=" gumilev.txt 3

คำสั่งยอมรับที่อยู่เดียวเท่านั้น ไม่ยอมรับช่วงเวลา

คำสั่งย

คำสั่งนี้จะแทนที่อักขระจากส่วน PATTERN ด้วยอักขระจากส่วน REPLACE ซึ่งทำงานเหมือนกับโปรแกรม ตร.

$ echo Car - มรดกแห่งอดีต | sed "y/Auto/Paro/" รถจักรไอน้ำ - มรดกจากอดีต

ทีม ใช้งานได้เฉพาะเมื่อจำนวนอักขระในรูปแบบเท่ากับจำนวนอักขระใน REPLACEMENT

สคริปต์โปรแกรม sed

เพื่อที่จะใช้โปรแกรมแก้ไข sed เป็นโปรแกรมแก้ไขข้อความที่มีคุณสมบัติครบถ้วน คุณจะต้องเชี่ยวชาญการเขียนสคริปต์ sed โปรแกรม sed มีภาษาโปรแกรมที่เรียบง่ายของตัวเอง ซึ่งช่วยให้คุณสามารถเขียนสคริปต์ที่สามารถทำงานได้อย่างมหัศจรรย์

บทความนี้ไม่สามารถมีคำอธิบายของสคริปต์ sed ได้ เช่นเดียวกับที่ผู้เขียนไม่ได้กำหนดหน้าที่ของตัวเองในการเรียนรู้ภาษาการเขียนโปรแกรม sed ในบทความนี้ ฉันมุ่งเน้นไปที่การใช้โปรแกรมแก้ไข sed บนบรรทัดคำสั่ง โดยคำนึงถึงการใช้มันเป็นตัวกรองในไปป์ ด้วยเหตุนี้ ฉันจึงละเว้นคำสั่ง sed จำนวนมากที่ใช้ในสคริปต์ sed เท่านั้น

มีแฟน ๆ ของบรรณาธิการ sed มากมายและมีบทความมากมายเกี่ยวกับหัวข้อการเขียนสคริปต์รวมถึงบน RuNet ดังนั้นสำหรับผู้ที่สนใจโปรแกรมที่ยอดเยี่ยมนี้ การขยายความรู้จึงไม่ใช่เรื่องยาก

โปรแกรม sed และอักขระซีริลลิก

ดังที่เห็นได้จากตัวอย่างในบทความนี้ โปรแกรม sed บนระบบ Russified ที่เหมาะสมนั้นใช้ภาษาที่ "ยอดเยี่ยมและทรงพลัง" ได้อย่างคล่องแคล่ว

สรุปโปรแกรม sed

โปรแกรม sed เป็นตัวแก้ไขโฟลว์ข้อมูลแบบมัลติฟังก์ชั่น ซึ่งขาดไม่ได้สำหรับ:

  • การแก้ไขอาร์เรย์ข้อความขนาดใหญ่
  • การแก้ไขไฟล์ทุกขนาดเมื่อลำดับการแก้ไขซับซ้อนเกินไป
  • การแก้ไขข้อมูลตามที่มี รวมถึงแบบเรียลไทม์ นั่นคือในกรณีที่การใช้โปรแกรมแก้ไขข้อความเชิงโต้ตอบเป็นเรื่องยากหรือเป็นไปไม่ได้เลย

หากต้องการเชี่ยวชาญโปรแกรม sed อย่างเต็มรูปแบบ จะต้องใช้เวลาหลายสัปดาห์หรือหลายเดือน เนื่องจากต้องใช้:

  • เรียนรู้นิพจน์ทั่วไป
  • เรียนรู้การเขียนสคริปต์ sed โดยการเรียนรู้ภาษาโปรแกรมง่ายๆ ที่ใช้ในสคริปต์เหล่านี้

ในทางกลับกัน การเรียนรู้คำสั่งต่างๆ ที่พบบ่อยที่สุดใน sed editor นั้นไม่ยากไปกว่าคำสั่ง Unix ใดๆ ฉันหวังว่าบทความนี้จะช่วยคุณในเรื่องนี้

คำหลัง

จนถึงขณะนี้ ในบทความของซีรีส์ HuMan ฉันได้พยายามเปิดเผยแต่ละตัวเลือกโดยย่อ แต่ละพารามิเตอร์ของคำสั่งที่อธิบายไว้ อย่างน้อยที่สุดเพื่อให้บทความสามารถแทนที่มานาได้ ต่อไปผมจะยึดหลักนี้ต่อไป

บทความนี้เป็นข้อยกเว้น เนื่องจากไม่ได้อธิบายคุณลักษณะทั้งหมดของโปรแกรม คำอธิบายที่สมบูรณ์ไม่จำเป็นต้องมีบทความ แต่เป็นหนังสือ อย่างไรก็ตามบทความนี้ช่วยให้คุณเข้าใจแนวคิดเกี่ยวกับโปรแกรมแก้ไข sed และเริ่มต้นใช้งานโปรแกรมที่น่าทึ่งนี้โดยใช้คำสั่งทั่วไป


ผู้เขียน : ราเรส ไอโอเนอี
วันที่เผยแพร่: 19 พฤศจิกายน 2554
การแปล: A. Krivoshey
วันที่แปล: กรกฎาคม 2555

1. บทนำ

ยินดีต้อนรับสู่ส่วนที่สองของซีรีส์ของเราใน sed เวอร์ชัน GNU มี sed หลายเวอร์ชันที่พร้อมใช้งานบนแพลตฟอร์มที่แตกต่างกัน แต่เราจะมุ่งเน้นไปที่ GNU sed เวอร์ชัน 4.x หลายๆ คนคงเคยได้ยินเกี่ยวกับ sed หรือเคยใช้มันมาแล้ว ซึ่งน่าจะเป็นเครื่องมือทดแทน แต่นี่เป็นเพียงจุดประสงค์หนึ่งของ sed และเราจะพยายามแสดงให้คุณเห็นทุกแง่มุมของการใช้ยูทิลิตี้นี้ ชื่อย่อมาจาก "Stream EDitor" และคำว่า "stream" ในกรณีนี้อาจหมายถึงไฟล์ ช่อง หรือเพียงแค่ stdin เราหวังว่าคุณจะมีความรู้พื้นฐานเกี่ยวกับ Linux อยู่แล้ว และหากคุณเคยทำงานกับนิพจน์ทั่วไปแล้วหรืออย่างน้อยก็รู้ว่ามันคืออะไร ทุกอย่างจะง่ายขึ้นสำหรับคุณ Space ไม่อนุญาตให้เรารวมบทช่วยสอนที่สมบูรณ์เกี่ยวกับนิพจน์ทั่วไป แต่เราจะพูดถึงแนวคิดพื้นฐานและให้ตัวอย่างวิธีใช้ sed มากมาย

2. การติดตั้ง

ไม่จำเป็นต้องพูดอะไรมากที่นี่ เป็นไปได้มากว่าคุณได้ติดตั้ง sed ทั้งหมดแล้ว เนื่องจากมีการใช้งานโดยสคริปต์ระบบต่างๆ รวมถึงผู้ใช้ Linux ที่ต้องการเพิ่มประสิทธิภาพการทำงาน คุณสามารถดูเวอร์ชันของ sed ที่คุณติดตั้งด้วยคำสั่ง:

$sed --version

ในระบบของฉัน คำสั่งนี้แสดงว่าฉันได้ติดตั้ง GNU sed 4.2.1 แล้ว พร้อมด้วยลิงก์ไปยังหน้าแรกของโปรแกรมและข้อมูลที่เป็นประโยชน์อื่นๆ แพ็คเกจนี้เรียกว่า "sed" โดยไม่คำนึงถึงการแจกจ่าย ยกเว้น Gentoo ซึ่งมีอยู่โดยปริยาย

3. แนวคิด

ก่อนที่เราจะไปไกลกว่านั้น เราคิดว่าสิ่งสำคัญคือต้องมุ่งเน้นไปที่สิ่งที่ "sed" ทำ เนื่องจากวลี "เครื่องมือแก้ไขสตรีม" ไม่ได้บอกเรามากนักเกี่ยวกับจุดประสงค์ของมัน sed รับข้อความเป็นอินพุต ดำเนินการตามที่ระบุในแต่ละบรรทัด (เว้นแต่จะระบุไว้เป็นอย่างอื่น) และส่งออกข้อความที่แก้ไข การดำเนินการที่ระบุสามารถเพิ่ม แทรก ลบ หรือแทนที่ได้ มันไม่ง่ายอย่างที่คิด คำเตือน มีตัวเลือกและตัวเลือกมากมายที่สามารถทำให้คำสั่ง sed เข้าใจได้ยากมาก ดังนั้น เราขอแนะนำให้คุณเรียนรู้พื้นฐานของนิพจน์ทั่วไปเพื่อทำความเข้าใจวิธีการทำงาน ก่อนที่เราจะเริ่มบทช่วยสอน เราอยากจะขอบคุณ Eric Pement และคนอื่นๆ สำหรับแรงบันดาลใจและสิ่งที่เขาทำเพื่อทุกคนที่ต้องการเรียนรู้และใช้ sed

4. นิพจน์ทั่วไป

เนื่องจากคำสั่ง sed (สคริปต์) ยังคงเป็นปริศนาสำหรับหลาย ๆ คน เรารู้สึกว่าผู้อ่านของเราควรเข้าใจแนวคิดพื้นฐาน แทนที่จะคัดลอกและวางคำสั่งแบบสุ่มสี่สุ่มห้าซึ่งพวกเขาไม่เข้าใจความหมาย เมื่อต้องการทำความเข้าใจว่านิพจน์ทั่วไปคืออะไร คำสำคัญคือ "การจับคู่" หรือถ้าให้เจาะจงกว่านั้นคือ "การจับคู่รูปแบบ" ตัวอย่างเช่น ในรายงานสำหรับแผนกของคุณ คุณเขียนชื่อ Nick ซึ่งหมายถึงสถาปนิกเครือข่าย แต่นิคจากไป และจอห์นก็เข้ามาแทนที่ ดังนั้นตอนนี้คุณต้องแทนที่คำว่านิคด้วยจอห์น หากไฟล์รายงานชื่อ report.txt คุณควรเรียกใช้คำสั่งต่อไปนี้:

$ cat report.txt / sed "s/Nick/John/g"> report_new.txt

ตามค่าเริ่มต้น sed ใช้ stdout คุณสามารถใช้ตัวดำเนินการเปลี่ยนเส้นทางเอาต์พุตดังที่แสดงในตัวอย่างด้านบน นี่เป็นตัวอย่างง่ายๆ แต่เราแสดงให้เห็นบางจุด: เราค้นหารายการที่ตรงกันทั้งหมดกับรูปแบบ "Nick" และแทนที่ด้วย "John" ในทุกกรณี โปรดทราบว่าการค้นหา sed จะคำนึงถึงตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ ดังนั้นโปรดใช้ความระมัดระวังและตรวจสอบไฟล์เอาต์พุตเพื่อให้แน่ใจว่าได้ทำการแทนที่ทั้งหมดแล้ว ตัวอย่างข้างต้นสามารถเขียนได้ดังนี้:

$ sed "s/Nick/John/g" report.txt > report_new.txt

โอเค คุณอาจพูดว่า แต่นิพจน์ทั่วไปอยู่ที่ไหน? ใช่ เราต้องการแสดงตัวอย่างก่อน และตอนนี้ก็มาถึงส่วนที่น่าสนใจ
หากคุณไม่แน่ใจว่าคุณเขียนว่า "nick" หรือ "Nick" และต้องการครอบคลุมทั้งสองกรณี คุณต้องใช้คำสั่ง sed "s/Nick/nick/John/g" แถบแนวตั้งมีความหมายที่คุณควรรู้หากคุณเคยเรียนภาษา C กล่าวคือ สำนวนของคุณจะตรงกับ "nick" หรือ "Nick" ดังที่คุณเห็นด้านล่าง ช่องนี้สามารถนำมาใช้ในรูปแบบอื่นได้ แต่ความหมายยังคงเหมือนเดิม ตัวดำเนินการอื่นๆ ที่ใช้กันทั่วไปในนิพจน์ทั่วไปคือ "?" ซึ่งตรงกับการซ้ำของอักขระก่อนหน้าเป็นศูนย์หรือหนึ่งครั้ง (นั่นคือ flavou?r จะตรงกับรสชาติและรสชาติ) "*" - ศูนย์หรือมากกว่าครั้ง "+" - หนึ่งครั้งหรือมากกว่านั้น "^" จับคู่ที่จุดเริ่มต้นของบรรทัด และ "$" จับคู่ที่ตรงกันข้าม หากคุณเป็นผู้ใช้ vi หรือ vim หลายๆ อย่างอาจจะดูคุ้นเคยสำหรับคุณ ท้ายที่สุดแล้ว ยูทิลิตี้เหล่านี้ รวมถึง awk และ C ย้อนกลับไปในยุคแรกๆ ของ UNIX เราจะไม่พูดถึงหัวข้อนี้อีกต่อไปเนื่องจากจะเข้าใจความหมายของอักขระเหล่านี้ได้ง่ายกว่าพร้อมตัวอย่าง แต่คุณควรทราบว่ามีการใช้งานนิพจน์ทั่วไปที่หลากหลาย: POSIX, POSIX Extended, Perl รวมถึงการใช้งาน fuzzy Regular ต่างๆ สำนวนที่รับรองว่าจะทำให้คุณปวดหัว

5. ตัวอย่างการใช้ sed

ไวยากรณ์คำสั่ง คำอธิบาย
sed "s/Nick/John/g" report.txt แทนที่ Nick ทุกรายการด้วย John ในไฟล์ report.txt
sed "s/Nick/nick/John/g" report.txt แทนที่ Nick หรือ Nick ทุกรายการด้วย John
sed "s/^/ /" file.txt >file_new.txt เพิ่มช่องว่าง 8 ช่องทางด้านซ้ายของข้อความเพื่อปรับปรุงคุณภาพการพิมพ์
sed -n "/แน่นอน/,/สนใจคุณ \
จ่าย/p" myfile
แสดงหนึ่งย่อหน้าเริ่มต้นด้วย "แน่นอน" และลงท้ายด้วย "ความสนใจที่คุณจ่าย"
sed -n 12.18p ไฟล์.txt ส่งออกเฉพาะบรรทัด 12-18 ของ file.txt
sed 12,18d ไฟล์.txt พิมพ์ไฟล์ file.txt ทั้งหมด ยกเว้นบรรทัดที่ 12 ถึง 18
sed G ไฟล์.txt เพิ่มช่องว่างเป็นสองเท่าใน file.txt
sed -f script.sed ไฟล์ txt เขียนคำสั่งทั้งหมดไปที่ script.sed และดำเนินการคำสั่งเหล่านั้น
sed "5!s/แฮม/ชีส/" file.txt แทนที่แฮมด้วยชีสใน file.txt ยกเว้นบรรทัดที่ 5
sed "$d" file.txt ลบบรรทัดสุดท้าย
sed "/\(3\)/p" file.txt พิมพ์เฉพาะบรรทัดที่มีตัวเลขสามหลักติดต่อกัน
sed "/boom/!s/aaa/bb/" file.txt หากพบ "boom" ให้แทนที่ aaa ด้วย bb
sed "17,/disk/d" file.txt ลบบรรทัดทั้งหมดตั้งแต่บรรทัด 17 ถึง "disk"
เสียงสะท้อนหนึ่งสอง / sed "s/one/unos/I" แทนที่อันหนึ่งด้วย unos โดยไม่คำนึงถึงตัวพิมพ์ ดังนั้นมันจะพิมพ์ "unos TWO"
sed "G;G" file.txt เพิ่มช่องว่างสามเท่าในไฟล์
sed "s/.$//" file.txt วิธีแทนที่ dos2unix :)
sed "s/^[ ^t]*//" file.txt ลบช่องว่างทั้งหมดก่อนแต่ละบรรทัดใน file.txt
sed "s/[ ^t]*$//" file.txt ลบช่องว่างทั้งหมดที่ท้ายแต่ละบรรทัดใน file.txt
sed "s/^[ ^t]*//;s/[ ^]*$//" file.txt ลบช่องว่างทั้งหมดที่จุดเริ่มต้นและจุดสิ้นสุดของแต่ละบรรทัดใน file.txt
sed "s/foo/bar/" file.txt แทนที่ foo ด้วย bar เฉพาะในบรรทัดแรกเท่านั้น
sed "s/foo/bar/4" file.txt แทนที่ foo ด้วย bar เฉพาะในกรณีที่สี่ของบรรทัด
sed "s/foo/bar/g" file.txt แทนที่ foo ด้วย bar สำหรับการเกิดขึ้นของสตริงทั้งหมด
sed "/baz/s/foo/bar/g" file.txt แทนที่ foo ด้วย bar เฉพาะในกรณีที่สตริงมี baz
sed "/./,/^$/!d" file.txt ลบบรรทัดว่างที่ต่อเนื่องกันทั้งหมด ยกเว้น EOF
sed "/^$/N;/\n$/D" file.txt ลบบรรทัดว่างที่ต่อเนื่องกันทั้งหมด แต่ปล่อยบรรทัดว่างด้านบนไว้
sed "/./,$!d" file.txt ลบบรรทัดว่างนำหน้าทั้งหมด
sed -e:a -e "/^\n*$/($d;N;);/\n$/ba" \
ไฟล์.txt
ลบบรรทัดว่างต่อท้ายทั้งหมด
sed -e:a -e "/\\$/N; s/\\\n//; ทา" \
ไฟล์.txt
หากไฟล์ลงท้ายด้วย backsplash ให้ต่อเข้ากับไฟล์ถัดไป (มีประโยชน์สำหรับเชลล์สคริปต์)
sed "/regex/,+5/expr/" จับคู่ regex บวก 5 บรรทัดต่อไปนี้
sed "1~3d" file.txt ลบทุกๆ บรรทัดที่สาม โดยเริ่มจากบรรทัดแรก
sed -n "2~5p" file.txt พิมพ์ทุกๆ ห้าบรรทัด เริ่มจากบรรทัดที่สอง
sed "s/ick/John/g" report.txt อีกวิธีหนึ่งในการเขียนตัวอย่างข้างต้น คุณสามารถเสนอของคุณได้ไหม?
sed -n "/RE/(p;q;)" file.txt พิมพ์เฉพาะการจับคู่ RE (นิพจน์ทั่วไป) แรกเท่านั้น
sed "0,/RE/(//d;)" file.txt ลบเฉพาะนัดแรกเท่านั้น
sed "0,/RE/s//to_that/" file.txt เปลี่ยนแค่แมตช์แรกเท่านั้น
sed "s/^[^,]*,/9999,/" file.csv แทนที่ช่องแรกด้วย 9999 ในไฟล์ CSV
s/^ *\(.*[^ ]\) *$//\1//; s/" *, */"//g; : วนซ้ำ s// *\([^",/][^,/]*\) *, *//\1//g; s// *, *//\1//g; t วนซ้ำ s / *//////g;s// *///g;s/^/\(.*\)/$/\1/; สคริปต์ Sed เพื่อแปลงไฟล์ CSV เป็นไฟล์ที่มีตัวคั่นไปป์ (ใช้ได้กับ CSV บางประเภทเท่านั้น ซึ่งมีเครื่องหมายคำพูดและเครื่องหมายจุลภาคฝังอยู่)
sed ":a;s/\(^\/[^0-9.]\)\(\+\)\(\(3\)\)/\1\2,\3/g;ta" ไฟล์ .txt เปลี่ยนรูปแบบตัวเลขใน file.txt จาก 1234.56 เป็น 1.234.56
sed -r "s/\<(reg/exp)+/\U&/g" แปลงคำใดๆ ที่ขึ้นต้นด้วย reg หรือ exp เป็นตัวพิมพ์ใหญ่
sed "1.20 s/Johnson/White/g" file.txt แทนที่ Johnson ด้วยสีขาวเฉพาะในบรรทัดที่ 1 - 20
sed "1.20 !s/Johnson/White/g" file.txt ตัวอย่างก่อนหน้านี้กลับกัน (แทนที่ทุกที่ยกเว้นบรรทัดที่ 1-20)
sed "/จาก/,/จนถึง/ ( s/\ /magenta/g; \ s/\ /cyan/g; )" file.txt แทนที่ระหว่าง "จาก" และ "จนถึง" เท่านั้น
sed "/ENDNOTES:/,$ ( s/Schaff/Herzog/g; \ s/Kraft/Ebbing/g; )" file.txt แทนที่เฉพาะคำว่า "ENDNOTES:" เป็น EOF
sed "/./(H;$!d;);x;/regex/!d" file.txt พิมพ์ย่อหน้าเฉพาะเมื่อมี regex
sed -e "/./(H;$!d;)" -e "x;/RE1/!d;/RE2/!d;/RE3/!d" file.txt พิมพ์ย่อหน้าเฉพาะเมื่อมี RE1, RE2 และ RE3
sed "s/14"/สิบสี่นิ้ว/g" file.txt วิธีนี้คุณสามารถใช้เครื่องหมายคำพูดคู่ได้
sed "s/\/some\/UNIX\/path/\/a\/new\/path/g" file.txt การทำงานกับเส้นทาง Unix
sed "s///g" file.txt ลบอักขระทั้งหมดที่ขึ้นต้นด้วย a และลงท้ายด้วย g จาก file.txt
sed "s/\(.*\)foo/\1bar/" file.txt แทนที่ foo นัดสุดท้ายด้วยแถบ
sed "1!G;h;$!d" การแทนที่คำสั่ง tac
sed "/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//" การแทนที่คำสั่ง rev
ไฟล์ sed 10q.txt แทนที่คำสั่ง head
sed -e:a -e "$q;N;11,$D;ba" \ file.txt แทนที่คำสั่ง tail
sed "$!N; /^\(.*\)\n\1$/!P; D" \ file.txt การแทนที่คำสั่ง uniq
sed "$!N; s/^\(.*\)\n\1$/\1/;\ t; D" file.txt คำสั่งย้อนกลับ (เทียบเท่ากับ uniq -d)
sed "$!N;$!D" file.txt เทียบเท่ากับหาง -n 2
sed -n "$p" file.txt ... หาง -n 1 (หรือหาง -1)
sed "/regexp/!d" file.txt เทียบเท่ากับ grep
sed -n "/regexp/(g;1!p;);h" file.txt พิมพ์บรรทัดที่อยู่หน้าคู่แรกของนิพจน์ทั่วไป แต่ไม่รวมคู่ที่ตรงกัน
sed -n "/regexp/(n;p;)" file.txt พิมพ์บรรทัดหลังการจับคู่นิพจน์ทั่วไปครั้งแรก แต่ไม่รวมการจับคู่นั้นเอง
sed "/รูปแบบ/d" file.txt ลบรูปแบบการจับคู่บรรทัด
sed "/./!d" file.txt ลบบรรทัดว่างทั้งหมดออกจากไฟล์
sed "/^$/N;/\n$/N;//D" file.txt ลบบรรทัดว่างที่ต่อเนื่องกันทั้งหมด ยกเว้นสองบรรทัดแรก
sed -n "/^$/(p;h;);/./(x;/./p;)"\ file.txt ลบบรรทัดสุดท้ายของแต่ละย่อหน้า
sed "/^$/q" รับส่วนหัวของอีเมล
sed "1,/^$/d" รับเนื้อความของข้อความ
sed "/^เรื่อง: */!d; s///;q" รับเรื่องของจดหมาย
sed "s/^/> /" ใส่เครื่องหมายคำพูดของข้อความโดยการใส่ ">" ก่อนแต่ละบรรทัด
sed "s/^> //" คำสั่ง Reverse (ลบเครื่องหมายคำพูดออกจากข้อความ)
sed -e:a -e "s/<[^>]*>//g;/ ลบแท็ก HTML
sed "/./(H;d;);x;s/\n/=(NL)=/g" file.txt / sort \ / sed "1s/=(NL)=//;s/=( NL)=/\n/g" จัดเรียงย่อหน้าใน file.txt ตามลำดับตัวอักษร
sed "s@/usr/bin@&/local@g" path.txt แทนที่ /usr/bin ด้วย /usr/bin/local ใน path.txt
sed "s@^.*$@<<<&>>>@g" path.txt ลองและดู :)
sed "s/\(\/[^:]*\).*/\1/g" path.txt สมมติว่า path.txt มี $PATH ให้พิมพ์เฉพาะเส้นทางแรกในแต่ละบรรทัด
sed "s/\([^:]*\).*/\1/" /etc/passwd การแทนที่ awk - แสดงเฉพาะผู้ใช้จากไฟล์ passwd
echo "ยินดีต้อนรับสู่สิ่งที่เกินบรรยาย" / sed \ "s/\(\b\)/\(\1\)/g" (W) ยินดีต้อนรับ (T) o (T) เขา (G) eek (S) ปอย ชัดเจนโดยไม่ต้องอธิบาย
sed -e "/^$/,/^END/s/hills/\ mountains/g" file.txt แทนที่ "hills" ด้วย "mountains" เฉพาะในกลุ่มข้อความที่ขึ้นต้นด้วยบรรทัดว่างและลงท้ายด้วยบรรทัดที่มีอักขระ "END" 3 ตัวเท่านั้น
sed -e "/^#/d" /etc/services/more แสดงไฟล์บริการโดยไม่มีบรรทัดแสดงความคิดเห็น
sed "$s@\([^:]*\):\([^:]*\):\([^:]*\)@\3:\2:\1@g" path.txt กลับลำดับขององค์ประกอบในบรรทัดสุดท้ายของ path.txt
sed "/regex/(x;p;x;)" file.txt แทรกบรรทัดใหม่เหนือแต่ละบรรทัดที่ตรงกับนิพจน์ทั่วไป
sed "/AAA/!d; /BBB/!d; /CCC/!d" file.txt ค้นหาการจับคู่ AAA, BBB และ CCC ตามลำดับใดก็ได้
sed "/AAA.*BBB.*CCC/!d" file.txt ค้นหาการจับคู่ AAA, BBB และ CCC ตามลำดับที่กำหนด
sed -n "/^.\(65\)/p" file.txt พิมพ์บรรทัดที่มีความยาว 65 ตัวอักษรขึ้นไป
sed -n "/^.\(65\)/!p" file.txt พิมพ์บรรทัดที่มีความยาว 65 อักขระหรือน้อยกว่า
sed "/regex/G" file.txt แทรกบรรทัดว่างด้านล่างแต่ละบรรทัด
sed "/regex/(x;p;x;G;)" file.txt แทรกบรรทัดว่างด้านบนและด้านล่างแต่ละบรรทัด
sed = file.txt / sed "N;s/\n/\t/" เส้นตัวเลขใน file.txt
sed -e:a -e "s/^.\(1.78\)$/ &/;ta" file.txt จัดข้อความชิดขวา
sed -e:a -e "s/^.\(1.77\)$/ &/;ta" -e "s/\(*\)\1/\1/" file.txt จัดข้อความให้อยู่ตรงกลาง

6. บทสรุป

นี่เป็นเพียงส่วนหนึ่งของสิ่งที่อาจกล่าวได้เกี่ยวกับ sed แต่บทความชุดนี้ถือเป็นแนวทางปฏิบัติมากกว่าที่เราหวังว่าจะช่วยให้คุณเห็นถึงพลังของยูทิลิตี้ Unix และทำให้งานของคุณมีประสิทธิภาพมากขึ้น

ครั้งล่าสุดที่เราพูดถึงฟังก์ชั่นใน bash script โดยเฉพาะวิธีการเรียกมันจากบรรทัดคำสั่ง หัวข้อของเราในวันนี้เป็นเครื่องมือที่มีประโยชน์มากสำหรับการประมวลผลข้อมูลสตริง - ยูทิลิตี Linux ที่เรียกว่า sed มักใช้เพื่อทำงานกับข้อความในรูปแบบของไฟล์บันทึก การกำหนดค่า และไฟล์อื่นๆ



หากคุณกำลังจัดการข้อมูลใดๆ ในสคริปต์ bash คุณจะต้องทำความคุ้นเคยกับเครื่องมือต่างๆ sed และ gawk ที่นี่เราจะมุ่งเน้นไปที่ sed และการทำงานกับข้อความ เนื่องจากนี่เป็นขั้นตอนที่สำคัญมากในการเดินทางของเราผ่านการพัฒนา bash script ที่กว้างใหญ่

ตอนนี้เราจะดูพื้นฐานของการทำงานกับ sed และดูตัวอย่างการใช้เครื่องมือนี้มากกว่าสามสิบตัวอย่าง

พื้นฐานการทำงานกับ sed

ยูทิลิตี้ sed เรียกว่าโปรแกรมแก้ไขข้อความแบบสตรีมมิ่ง ในโปรแกรมแก้ไขข้อความเชิงโต้ตอบเช่น nano คุณสามารถทำงานกับข้อความโดยใช้คีย์บอร์ด แก้ไขไฟล์ การเพิ่ม ลบ หรือเปลี่ยนแปลงข้อความ Sed ช่วยให้คุณสามารถแก้ไขสตรีมข้อมูลตามกฎที่นักพัฒนากำหนด นี่คือลักษณะของคำสั่งนี้:

ไฟล์ตัวเลือก $sed
ตามค่าเริ่มต้น sed จะใช้กฎที่ระบุเมื่อเรียกใช้ ซึ่งแสดงเป็นชุดคำสั่ง กับ STDIN สิ่งนี้ทำให้คุณสามารถส่งข้อมูลไปยัง sed ได้โดยตรง

ตัวอย่างเช่นเช่นนี้:

$ echo "นี่คือการทดสอบ" | sed "s/test/การทดสอบอื่น/"
นี่คือสิ่งที่เกิดขึ้นเมื่อคุณรันคำสั่งนี้


ตัวอย่างง่ายๆ ของการเรียก sed

ในกรณีนี้ sed จะแทนที่คำว่า "test" ในบรรทัดที่ส่งผ่านสำหรับการประมวลผลด้วยคำว่า "การทดสอบอื่น" ในการกำหนดกฎสำหรับการประมวลผลข้อความที่อยู่ในเครื่องหมายคำพูด จะใช้เครื่องหมายทับ ในกรณีของเรา เราใช้คำสั่งเช่น s/pattern1/pattern2/ ตัวอักษร "s" เป็นตัวย่อของคำว่า "ทดแทน" นั่นคือเรามีคำสั่งทดแทน Sed ดำเนินการคำสั่งนี้จะตรวจสอบข้อความที่ส่งและแทนที่ชิ้นส่วนที่พบในนั้น (เราจะพูดถึงชิ้นส่วนใดด้านล่าง) ที่สอดคล้องกับรูปแบบ 1 ด้วยรูปแบบ 2

ด้านบนนี้เป็นตัวอย่างเบื้องต้นของการใช้ sed เพื่อให้คุณเร่งความเร็วได้ ในความเป็นจริง sed สามารถใช้ในสถานการณ์การประมวลผลข้อความที่ซับซ้อนมากขึ้น เช่น การทำงานกับไฟล์

ด้านล่างนี้เป็นไฟล์ที่มีข้อความและผลลัพธ์ของการประมวลผลด้วยคำสั่งนี้:

$ sed "s/test/การทดสอบอื่น" ./myfile


ไฟล์ข้อความและผลลัพธ์ของการประมวลผล

วิธีนี้จะใช้วิธีการเดียวกับที่เราใช้ด้านบน แต่ตอนนี้ sed จะประมวลผลข้อความที่เก็บไว้ในไฟล์ อย่างไรก็ตาม หากไฟล์มีขนาดใหญ่พอ คุณจะสังเกตเห็นว่า sed ประมวลผลข้อมูลเป็นชิ้น ๆ และแสดงสิ่งที่ประมวลผลบนหน้าจอ โดยไม่ต้องรอให้ไฟล์ทั้งหมดได้รับการประมวลผล

Sed จะไม่เปลี่ยนแปลงข้อมูลในไฟล์ที่กำลังประมวลผล โปรแกรมแก้ไขอ่านไฟล์ ประมวลผลสิ่งที่อ่าน และส่งผลลัพธ์ผลลัพธ์ไปยัง STDOUT เพื่อให้แน่ใจว่าไฟล์ต้นฉบับไม่มีการเปลี่ยนแปลง ก็เพียงพอที่จะเปิดไฟล์ดังกล่าวหลังจากที่โอนไปยัง sed แล้ว หากจำเป็น sed เอาต์พุตสามารถเปลี่ยนเส้นทางไปยังไฟล์ได้ ซึ่งอาจเขียนทับไฟล์เก่า หากคุณคุ้นเคยกับบทความก่อนหน้าในชุดนี้ ซึ่งพูดถึงการเปลี่ยนเส้นทางสตรีมอินพุตและเอาต์พุต คุณควรจะทำเช่นนี้ได้

การดำเนินการชุดคำสั่งเมื่อเรียก sed

หากต้องการดำเนินการหลายอย่างกับข้อมูล ให้ใช้สวิตช์ -e เมื่อโทร sed ตัวอย่างเช่น ต่อไปนี้เป็นวิธีจัดระเบียบการแทนที่ส่วนข้อความสองส่วน:

$ sed -e "s/This/That/; s/test/another test/" ./myfile


ใช้สวิตช์ -e เมื่อโทร sed

คำสั่งทั้งสองใช้กับข้อความแต่ละบรรทัดจากไฟล์ ต้องคั่นด้วยเครื่องหมายอัฒภาค และไม่ควรมีช่องว่างระหว่างส่วนท้ายของคำสั่งและเครื่องหมายอัฒภาค
หากต้องการป้อนรูปแบบการประมวลผลข้อความหลายรูปแบบเมื่อเรียก sed คุณสามารถหลังจากป้อนเครื่องหมายคำพูดเดี่ยวแรกแล้ว ให้กด Enter จากนั้นป้อนแต่ละกฎในบรรทัดใหม่ โดยไม่ลืมเครื่องหมายคำพูดปิด:

$ sed -e "> s/นี่/นั่น/ > s/test/การทดสอบอื่น/" ./myfile
นี่คือสิ่งที่จะเกิดขึ้นหลังจากดำเนินการคำสั่งที่แสดงในแบบฟอร์มนี้แล้ว


อีกวิธีในการทำงานกับ sed

การอ่านคำสั่งจากไฟล์

หากคุณมีคำสั่ง sed จำนวนมากที่จำเป็นต้องใช้ในการประมวลผลข้อความ โดยปกติวิธีที่ดีที่สุดคือเขียนคำสั่งเหล่านั้นลงในไฟล์ล่วงหน้า หากต้องการระบุไฟล์ sed ที่มีคำสั่ง ให้ใช้สวิตช์ -f:

นี่คือเนื้อหาของไฟล์ mycommands:

S/นี่/นั่น/ s/ทดสอบ/ทดสอบอื่น/
มาเรียก sed โดยส่งไฟล์พร้อมคำสั่งและไฟล์ที่จะประมวลผลให้กับเอดิเตอร์:

$ sed -f mycommands myfile
ผลลัพธ์เมื่อเรียกใช้คำสั่งดังกล่าวคล้ายกับผลลัพธ์ที่ได้รับในตัวอย่างก่อนหน้านี้


การใช้ไฟล์คำสั่งเมื่อเรียก sed

แทนที่แฟล็กคำสั่ง

ลองดูตัวอย่างต่อไปนี้อย่างใกล้ชิด

$sed "s/test/another test/" myfile
นี่คือสิ่งที่มีอยู่ในไฟล์และสิ่งที่จะได้รับหลังจาก sed ประมวลผลแล้ว


ไฟล์ต้นฉบับและผลลัพธ์ของการประมวลผล

โดยปกติคำสั่งแทนที่จะจัดการไฟล์หลายบรรทัด แต่จะแทนที่เฉพาะข้อความที่ค้นหาครั้งแรกในแต่ละบรรทัดเท่านั้น ในการแทนที่รูปแบบที่เกิดขึ้นทั้งหมด คุณต้องใช้แฟล็กที่เหมาะสม

รูปแบบการเขียนคำสั่งทดแทนเมื่อใช้แฟล็กมีลักษณะดังนี้:

S/รูปแบบ/การเปลี่ยน/ธง
การดำเนินการตามคำสั่งนี้สามารถแก้ไขได้หลายวิธี

  • เมื่อส่งหมายเลข หมายเลขซีเรียลของการเกิดขึ้นของรูปแบบในสตริงจะถูกนำมาพิจารณาด้วย และเหตุการณ์นี้เองที่จะถูกแทนที่
  • แฟล็ก g บ่งชี้ว่าเหตุการณ์ทั้งหมดของรูปแบบในสตริงควรได้รับการประมวลผล
  • ธง p บ่งชี้ว่าเนื้อหาของสตริงต้นฉบับควรถูกพิมพ์
  • ค่าสถานะไฟล์ w บอกให้คำสั่งเขียนผลการประมวลผลข้อความลงในไฟล์
ลองพิจารณาใช้เวอร์ชันแรกของคำสั่งการแทนที่ โดยระบุตำแหน่งของการแทนที่ของแฟรกเมนต์ที่ต้องการ:

$ sed "s/test/another test/2" myfile

การเรียกคำสั่ง replacement ระบุตำแหน่งของแฟรกเมนต์ที่จะถูกแทนที่

ที่นี่เราระบุหมายเลข 2 เป็นแฟล็กการแทนที่ สิ่งนี้นำไปสู่ความจริงที่ว่ามีเพียงการเกิดขึ้นครั้งที่สองของรูปแบบที่ต้องการในแต่ละบรรทัดเท่านั้นที่ถูกแทนที่ ทีนี้มาลองใช้แฟล็กการแทนที่โกลบอล - g:

$ sed "s/test/another test/g" myfile
ดังที่เห็นได้จากผลลัพธ์เอาต์พุต คำสั่งดังกล่าวจะแทนที่รูปแบบที่เกิดขึ้นทั้งหมดในข้อความ


การทดแทนระดับโลก

แฟล็กคำสั่งแทนที่ p อนุญาตให้คุณพิมพ์บรรทัดที่พบรายการที่ตรงกัน ในขณะที่ตัวเลือก -n ที่ระบุเมื่อเรียกใช้ sed จะระงับเอาต์พุตปกติ:

$ sed -n "s/test/another test/p" myfile
ด้วยเหตุนี้ เมื่อเปิดใช้งาน sed ในการกำหนดค่านี้ ระบบจะแสดงเฉพาะบรรทัด (ในกรณีของเราคือหนึ่งบรรทัด) ที่พบส่วนของข้อความที่ระบุ


การใช้แฟล็กคำสั่งแทนที่ p

ลองใช้แฟล็ก w ซึ่งช่วยให้คุณบันทึกผลลัพธ์ของการประมวลผลข้อความลงในไฟล์ได้:

$ sed "s/test/another test/w เอาท์พุต" myfile


บันทึกผลการประมวลผลข้อความลงในไฟล์

จะเห็นได้อย่างชัดเจนว่าในระหว่างการดำเนินการของคำสั่ง ข้อมูลจะถูกส่งออกไปยัง STDOUT ในขณะที่บรรทัดที่ประมวลผลจะถูกเขียนไปยังไฟล์ที่มีชื่อที่ระบุหลัง w

อักขระตัวคั่น

ลองนึกภาพการแทนที่ /bin/bash ด้วย /bin/csh ในไฟล์ /etc/passwd งานไม่ได้ยากขนาดนั้น:

$ sed "s/\/bin\/bash/\/bin\/csh/" /etc/passwd
อย่างไรก็ตาม สิ่งนี้ดูไม่ค่อยดีนัก ประเด็นก็คือเนื่องจากมีการใช้เครื่องหมายทับเป็นอักขระตัวคั่น จึงต้องหลีกเลี่ยงอักขระเดียวกันในสตริงที่ส่งไปยัง sed ส่งผลให้ความสามารถในการอ่านคำสั่งลดลง

โชคดีที่ sed ช่วยให้เราสามารถกำหนดอักขระตัวคั่นของเราเองเพื่อใช้ในคำสั่งแทนที่ ตัวคั่นคืออักขระตัวแรกที่ปรากฏหลังจาก s:

$ sed "s!/bin/bash!/bin/csh!" /etc/passwd
ในกรณีนี้ เครื่องหมายอัศเจรีย์จะถูกใช้เป็นตัวคั่น ส่งผลให้โค้ดอ่านง่ายขึ้นและดูเรียบร้อยกว่าเดิมมาก

การเลือกส่วนของข้อความสำหรับการประมวลผล

จนถึงตอนนี้ เราได้เรียก sed ให้ประมวลผลสตรีมข้อมูลทั้งหมดที่ส่งไปยังตัวแก้ไข ในบางกรณี การใช้ sed คุณจำเป็นต้องประมวลผลข้อความเพียงบางส่วนเท่านั้น - บรรทัดหรือกลุ่มบรรทัดเฉพาะ เพื่อให้บรรลุเป้าหมายนี้ คุณสามารถใช้สองแนวทาง:
  • กำหนดขีดจำกัดจำนวนแถวที่จะประมวลผล
  • ระบุตัวกรองที่ต้องประมวลผลแถวที่เกี่ยวข้อง
ลองพิจารณาแนวทางแรก มีสองตัวเลือกที่เป็นไปได้ที่นี่ ประการแรกที่กล่าวถึงด้านล่าง เกี่ยวข้องกับการระบุจำนวนหนึ่งบรรทัดที่ต้องดำเนินการ:

$sed "2s/test/another test/" myfile


ประมวลผลเพียงบรรทัดเดียว หมายเลขที่ระบุเมื่อโทร sed

ตัวเลือกที่สองคือช่วงของสตริง:

$ sed "2.3s/test/another test/" myfile


กำลังประมวลผลช่วงของแถว

นอกจากนี้ คุณยังสามารถเรียกใช้คำสั่งแทนที่เพื่อให้ไฟล์ได้รับการประมวลผลจากบรรทัดหนึ่งไปยังจุดสิ้นสุด:

$ sed "2,$s/test/another test/" myfile


กำลังประมวลผลไฟล์จากบรรทัดที่สองไปจนสุด

ในการใช้คำสั่งแทนที่เพื่อประมวลผลเฉพาะแถวที่ตรงกับตัวกรองที่กำหนด จะต้องเรียกคำสั่งดังนี้:

$ sed "/likegeeks/s/bash/csh/" /etc/passwd
โดยการเปรียบเทียบกับสิ่งที่กล่าวไว้ข้างต้น เทมเพลตจะถูกส่งไปก่อนชื่อคำสั่ง s


กำลังประมวลผลแถวที่ตรงกับตัวกรอง

ที่นี่เราใช้ตัวกรองที่เรียบง่ายมาก เพื่อที่จะใช้ประโยชน์จากความสามารถของแนวทางนี้อย่างเต็มที่ คุณสามารถใช้นิพจน์ทั่วไปได้ เราจะพูดถึงสิ่งเหล่านี้ในเอกสารชุดใดชุดหนึ่งต่อไปนี้ในชุดนี้

การลบแถว

ยูทิลิตี sed มีประโยชน์ไม่เพียงแต่สำหรับการแทนที่ลำดับอักขระในสตริงด้วยอีกลำดับหนึ่งเท่านั้น ด้วยความช่วยเหลือ กล่าวคือ การใช้คำสั่ง d คุณสามารถลบบรรทัดออกจากสตรีมข้อความได้

การเรียกคำสั่งมีลักษณะดังนี้:

$sed "3d" ไฟล์ของฉัน
เราต้องการให้บรรทัดที่สามถูกลบออกจากข้อความ โปรดทราบว่านี่ไม่ใช่ไฟล์ ไฟล์จะยังคงไม่เปลี่ยนแปลง การลบจะส่งผลต่อเอาต์พุตที่สร้างโดย sed เท่านั้น


การลบบรรทัดที่สาม

หากคุณไม่ระบุหมายเลขบรรทัดที่จะลบเมื่อเรียกใช้คำสั่ง d บรรทัดทั้งหมดในสตรีมจะถูกลบ

ต่อไปนี้เป็นวิธีใช้คำสั่ง d กับช่วงของสตริง:

$sed "2,3d" ไฟล์ของฉัน


ลบช่วงของแถว

ต่อไปนี้เป็นวิธีลบบรรทัดตั้งแต่บรรทัดที่กำหนดไปจนถึงท้ายไฟล์:

$sed "3,$d" ไฟล์ของฉัน


การลบบรรทัดต่อท้ายไฟล์

แถวสามารถลบได้โดยใช้รูปแบบต่อไปนี้:

$ sed "/test/d" myfile


การลบแถวโดยใช้รูปแบบ

เมื่อเรียก d คุณสามารถระบุคู่ของรูปแบบ - เส้นที่เกิดรูปแบบและเส้นที่อยู่ระหว่างนั้นจะถูกลบ:

$ sed "/วินาที/,/สี่/d" myfile


การลบช่วงของแถวโดยใช้ไวด์การ์ด

การแทรกข้อความลงในสตรีม

ด้วย sed คุณสามารถแทรกข้อมูลลงในสตรีมข้อความโดยใช้คำสั่ง i และคำสั่ง:
  • คำสั่ง i จะเพิ่มบรรทัดใหม่ก่อนหน้าบรรทัดที่กำหนด
  • คำสั่ง a จะเพิ่มบรรทัดใหม่หลังจากบรรทัดที่กำหนด
ลองดูตัวอย่างการใช้คำสั่ง i:

$ echo "การทดสอบอื่น" | sed "ฉัน\ทดสอบครั้งแรก"


ทีมฉัน

ตอนนี้เรามาดูคำสั่ง:

$ echo "การทดสอบอื่น" | sed "a\การทดสอบครั้งแรก"


คำสั่งก

อย่างที่คุณเห็น คำสั่งเหล่านี้จะเพิ่มข้อความก่อนหรือหลังข้อมูลจากสตรีม จะทำอย่างไรถ้าคุณต้องการเพิ่มบรรทัดตรงกลาง?

ที่นี่เราจะช่วยเหลือโดยระบุหมายเลขของบรรทัดอ้างอิงในสตรีมหรือเทมเพลต โปรดทราบว่าการกำหนดที่อยู่สตริงเป็นช่วงจะใช้ไม่ได้ที่นี่ เรียกคำสั่ง i โดยระบุหมายเลขบรรทัดก่อนหน้าซึ่งคุณต้องแทรกบรรทัดใหม่:

$ sed "2i\นี่คือบรรทัดที่แทรกไว้" ไฟล์ของฉัน


คำสั่ง i ด้วยหมายเลขบรรทัดอ้างอิง

ลองทำเช่นเดียวกันกับคำสั่ง:

$ sed "2a\นี่คือบรรทัดต่อท้าย" ไฟล์ของฉัน


สั่ง a ด้วยหมายเลขบรรทัดอ้างอิง

สังเกตความแตกต่างในวิธีการทำงานของคำสั่ง i และ a บรรทัดแรกจะแทรกบรรทัดใหม่ก่อนบรรทัดที่ระบุ บรรทัดที่สองหลังจากนั้น

การแทนที่สตริง

คำสั่ง c ช่วยให้คุณสามารถเปลี่ยนเนื้อหาของข้อความทั้งบรรทัดในสตรีมข้อมูล เมื่อเรียกคุณจะต้องระบุหมายเลขบรรทัดแทนที่จะเพิ่มข้อมูลใหม่ลงในสตรีม:

$ sed "3c\นี่คือบรรทัดที่แก้ไข" ไฟล์ของฉัน


การแทนที่สตริงทั้งหมด

หากคุณใช้รูปแบบในรูปแบบข้อความธรรมดาหรือนิพจน์ทั่วไปเมื่อเรียกใช้คำสั่ง สตริงทั้งหมดที่ตรงกับรูปแบบจะถูกแทนที่:

$ sed "/นี่คือ/c นี่คือบรรทัดข้อความที่มีการเปลี่ยนแปลง" ไฟล์ของฉัน


การแทนที่สตริงโดยใช้รูปแบบ

การแทนที่อักขระ

คำสั่ง y ทำงานกับอักขระแต่ละตัว โดยแทนที่ตามข้อมูลที่ส่งไปเมื่อมีการเรียก:

$sed "y/123/567/" myfile


การแทนที่อักขระ

เมื่อใช้คำสั่งนี้ คุณต้องคำนึงว่าคำสั่งนี้ใช้กับสตรีมข้อความทั้งหมด ไม่สามารถจำกัดเฉพาะอักขระที่ปรากฏได้

การแสดงหมายเลขบรรทัด

หากคุณโทร sed โดยใช้คำสั่ง = ยูทิลิตี้จะพิมพ์หมายเลขบรรทัดในสตรีมข้อมูล:

$sed "=" myfile


การแสดงหมายเลขบรรทัด

โปรแกรมแก้ไขสตรีมแสดงหมายเลขบรรทัดก่อนเนื้อหา

หากคุณส่งรูปแบบไปยังคำสั่งนี้และใช้สวิตช์ sed -n เฉพาะหมายเลขบรรทัดที่ตรงกับรูปแบบเท่านั้นที่จะถูกพิมพ์:

$sed -n "/test/=" myfile


การพิมพ์หมายเลขบรรทัดที่ตรงกับรูปแบบ

การอ่านข้อมูลแทรกจากไฟล์

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

ลองดูตัวอย่าง:

$sed "3r ไฟล์ใหม่" myfile


การแทรกเนื้อหาไฟล์ลงในสตรีม

ที่นี่เนื้อหาของไฟล์ newfile ถูกแทรกไว้หลังบรรทัดที่สามของไฟล์ myfile

นี่คือสิ่งที่เกิดขึ้นหากคุณใช้รูปแบบเมื่อเรียกใช้คำสั่ง r:

$ sed "/test/r newfile" myfile


การใช้ wildcard เมื่อเรียกใช้คำสั่ง r

เนื้อหาของไฟล์จะถูกแทรกหลังแต่ละบรรทัดที่ตรงกับรูปแบบ

ตัวอย่าง

ลองจินตนาการถึงงานดังกล่าว มีไฟล์หนึ่งซึ่งมีลำดับอักขระบางตัวซึ่งในตัวมันเองไม่มีความหมายซึ่งจะต้องถูกแทนที่ด้วยข้อมูลที่นำมาจากไฟล์อื่น กล่าวคือปล่อยให้เป็นไฟล์ไฟล์ใหม่ที่ลำดับอักขระ DATA มีบทบาทเป็นตัวยึดตำแหน่ง ข้อมูลที่ต้องทดแทน DATA จะถูกจัดเก็บไว้ในไฟล์ข้อมูล

คุณสามารถแก้ไขปัญหานี้ได้โดยใช้คำสั่ง r และ d ของโปรแกรมแก้ไข sed stream:

$ Sed "/DATA>/ ( r ไฟล์ใหม่ d)" myfile


การแทนที่ตัวยึดตำแหน่งด้วยข้อมูลจริง

อย่างที่คุณเห็น sed เพิ่มสองบรรทัดจากไฟล์ข้อมูลไปยังสตรีมเอาท์พุต แทนที่จะเป็นตัวยึดตำแหน่ง DATA

ผลลัพธ์

วันนี้เรามาดูพื้นฐานของการทำงานกับโปรแกรมแก้ไข sed stream อันที่จริง sed เป็นหัวข้อใหญ่ การเรียนรู้สามารถเปรียบเทียบได้กับการเรียนรู้ภาษาการเขียนโปรแกรมใหม่ แต่เมื่อคุณเข้าใจพื้นฐานแล้ว คุณสามารถเชี่ยวชาญ sed ในระดับใดก็ได้ที่คุณต้องการ เป็นผลให้ความสามารถในการประมวลผลข้อความจะถูกจำกัดด้วยจินตนาการของคุณเท่านั้น

นั่นคือทั้งหมดสำหรับวันนี้ ครั้งต่อไปเราจะพูดถึงภาษาการประมวลผลข้อมูล awk

เรียนผู้อ่าน! คุณใช้ sed ในการทำงานประจำวันของคุณหรือไม่? ถ้าใช่โปรดแบ่งปันประสบการณ์ของคุณ