Android

วิธีใช้ sed เพื่อค้นหาและแทนที่สตริงในไฟล์

What the Waters Left Behind Trailer 2 (2018) Los Olvidados

What the Waters Left Behind Trailer 2 (2018) Los Olvidados

สารบัญ:

Anonim

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

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

เราจะพูดถึงวิธีการค้นหาและแทนที่สตริงด้วย sed นอกจากนี้เราจะแสดงวิธีการค้นหาและแทนที่แบบเรียกซ้ำ

ค้นหาและแทนที่สตริงด้วย sed

มีรุ่นหลายรุ่นด้วยความแตกต่างระหว่างการทำงานบางอย่าง macOS ใช้รุ่น BSD และการแจกแจงลินุกซ์ส่วนใหญ่จะมาพร้อมกับ GNU sed ติดตั้งล่วงหน้า เราจะใช้เวอร์ชัน GNU

รูปแบบทั่วไปของการค้นหาและแทนที่ข้อความโดยใช้ sed จะใช้แบบฟอร์มต่อไปนี้:

sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE

  • -i - โดยค่าเริ่มต้น sed เขียนเอาต์พุตไปยังเอาต์พุตมาตรฐาน ตัวเลือกนี้บอกให้ sed แก้ไขไฟล์ให้เข้าที่ หากมีการให้ส่วนขยาย (ex -i.bak) ข้อมูลสำรองของไฟล์ต้นฉบับจะถูกสร้างขึ้น s - คำสั่งทดแทนอาจเป็นคำสั่งที่ใช้มากที่สุดใน sed / / / - อักขระตัวคั่น สามารถเป็นอักขระใดก็ได้ แต่โดยปกติจะใช้อักขระเครื่องหมายทับ ( / ) SEARCH_REGEX - สตริงปกติหรือนิพจน์ทั่วไปที่ต้องการค้นหา REPLACEMENT - สตริงการแทนที่ g - การเปลี่ยนสถานะทั่วโลก โดยค่าเริ่มต้น sed อ่านบรรทัดไฟล์ตามบรรทัดและเปลี่ยนเฉพาะการเกิดขึ้นครั้งแรกของ SEARCH_REGEX ในบรรทัด เมื่อมีการให้ค่าสถานะการแทนที่เกิดขึ้นทั้งหมดจะถูกแทนที่ INPUTFILE - ชื่อของไฟล์ที่คุณต้องการเรียกใช้คำสั่ง

เป็นวิธีปฏิบัติที่ดีในการใส่เครื่องหมายคำพูดรอบ ๆ อาร์กิวเมนต์เพื่อให้อักขระเมตาของเชลล์ไม่ขยาย

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

เพื่อวัตถุประสงค์ในการสาธิตเราจะใช้ไฟล์ต่อไปนี้:

file.txt

123 Foo foo foo foo /bin/bash Ubuntu foobar 456

sed -i 's/foo/linux/' file.txt

123 Foo linux foo linux /bin/bash Ubuntu foobar 456

ด้วยค่าสถานะการแทนที่ส่วนกลาง sed แทนที่การเกิดขึ้นของรูปแบบการค้นหาทั้งหมด:

sed -i 's/foo/linux/g' file.txt

123 Foo linux linux linux /bin/bash Ubuntu linuxbar 456

ดังที่คุณอาจสังเกตเห็นในตัวอย่างก่อนหน้า substring foo ภายในสตริง foobar จะถูกแทนที่ด้วย หากนี่ไม่ใช่พฤติกรรมที่ต้องการให้ใช้นิพจน์ขอบเขตของคำ ( \b ) ที่ปลายทั้งสองของสตริงการค้นหา สิ่งนี้ทำให้มั่นใจได้ว่าคำบางส่วนไม่ตรงกัน

sed -i 's/\bfoo\b/linux/g' file.txt

123 Foo linux linux linux /bin/bash Ubuntu foobar 456

ในการทำให้รูปแบบตัวพิมพ์เล็กและตัวพิมพ์เล็กไม่ตรงกันให้ใช้แฟล็ก I ในตัวอย่างด้านล่างเราใช้ทั้งธง g และ I :

sed -i 's/foo/linux/gI' file.txt

123 linux linux linux linux /bin/bash Ubuntu linuxbar 456

sed -i 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt

ตัวเลือกที่ง่ายและอ่านได้มากขึ้นคือการใช้อักขระตัวคั่นอื่น คนส่วนใหญ่ใช้แถบแนวตั้ง ( | ) หรือโคลอน (:) แต่คุณสามารถใช้อักขระอื่น ๆ ได้:

sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt

123 Foo foo foo foo /usr/bin/zsh Ubuntu foobar 456

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

sed -i 's/\b\{3}\b/number/g' file.txt

number Foo foo foo foo /bin/bash demo foobar number

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

ตัวอย่างเช่นหากคุณต้องการเพิ่มเครื่องหมายปีกกา {} รอบตัวเลข 3 หลักแต่ละประเภทให้พิมพ์:

sed -i 's/\b\{3}\b/{&}/g' file.txt

{123} Foo foo foo foo /bin/bash demo foobar {456}

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

sed -i.bak 's/foo/linux/g' file.txt

ls

file.txt file.txt.bak

ค้นหาและแทนที่แบบเรียกซ้ำ

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

คำสั่งต่อไปนี้จะค้นหาไฟล์ซ้ำในไดเรกทอรีการทำงานปัจจุบันและส่งชื่อไฟล์ไปยัง sed

find. -type f -exec sed -i 's/foo/bar/g' {} +

หากต้องการหลีกเลี่ยงปัญหาเกี่ยวกับไฟล์ที่มีช่องว่างในชื่อให้ใช้ตัวเลือก -print0 ซึ่งบอกให้ find เพื่อพิมพ์ชื่อไฟล์ตามด้วยอักขระ null และ xargs -0 เอาต์พุตไปยัง sed โดยใช้ xargs -0 :

find. -type f -print0 | xargs -0 sed -i 's/foo/bar/g'

หากต้องการยกเว้นไดเรกทอรีให้ใช้ตัวเลือก -not -path ตัวอย่างเช่นหากคุณกำลังแทนที่สตริงใน repo git ในพื้นที่ของคุณเพื่อแยกไฟล์ทั้งหมดที่ขึ้นต้นด้วย dot ( . ) ให้ใช้:

find. -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'

find. -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'

อีกทางเลือกหนึ่งคือการใช้คำสั่ง grep เพื่อค้นหาไฟล์ทั้งหมดที่มีรูปแบบการค้นหาซ้ำและจากนั้น sed ชื่อไฟล์ไปยัง sed :

grep -rlZ 'foo'. | xargs -0 sed -i.bak 's/foo/bar/g'

ข้อสรุป

แม้ว่ามันอาจดูซับซ้อนและซับซ้อน แต่ในตอนแรกการค้นหาและการแทนที่ข้อความในไฟล์ด้วย sed นั้นง่ายมาก

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

อาคารผู้โดยสาร