การแก้ไขแบบแทนที่ด้วย sed บน OS X


142

ฉันต้องการแก้ไขไฟล์ด้วย sed บน OS X ฉันใช้คำสั่งต่อไปนี้:

sed 's/oldword/newword/' file.txt

เอาต์พุตจะถูกส่งไปยังเทอร์มินัล file.txtไม่ได้รับการแก้ไข การเปลี่ยนแปลงจะถูกบันทึกไว้ในfile2.txtด้วยคำสั่งนี้:

sed 's/oldword/newword/' file1.txt > file2.txt

อย่างไรก็ตามฉันไม่ต้องการไฟล์อื่น ฉันแค่ต้องการแก้ไข file1.txt ฉันจะทำสิ่งนี้ได้อย่างไร

ฉันได้ลองใช้แฟล็ก -i แล้ว ซึ่งส่งผลให้เกิดข้อผิดพลาดดังต่อไปนี้:

sed: 1: "file1.txt": invalid command code f

2
คำสั่งที่แน่นอนที่คุณใช้เมื่อคุณลอง-iตั้งค่าสถานะคืออะไร
eldarerathis

คำตอบ:


282

คุณสามารถใช้การ-iตั้งค่าสถานะได้อย่างถูกต้องโดยให้คำต่อท้ายเพื่อเพิ่มลงในไฟล์ที่สำรองไว้ ขยายตัวอย่างของคุณ:

sed -i.bu 's/oldword/newword/' file1.txt

จะให้ไฟล์สองไฟล์แก่คุณ: หนึ่งไฟล์ที่มีชื่อfile1.txtที่มีการทดแทนและอีกไฟล์หนึ่งมีชื่อfile1.txt.buที่มีเนื้อหาต้นฉบับ

อันตรายเล็กน้อย

หากคุณต้องการเขียนทับไฟล์ต้นฉบับแบบทำลายล้างให้ใช้สิ่งต่อไปนี้:

sed -i '' 's/oldword/newword/' file1.txt
      ^ note the space

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

นอกเหนือจากการกำจัดต้นฉบับของคุณฉันไม่ทราบถึงอันตรายที่อาจเกิดขึ้นจากการหลอกลวงด้วยวิธีนี้ อย่างไรก็ตามควรสังเกตว่าหากการร้องขอนี้sedเป็นส่วนหนึ่งของสคริปต์ The Unix Way ™ (IMHO) จะใช้งานแบบsedไม่ทำลายล้างทดสอบว่าออกจากระบบเรียบร้อยแล้วและลบไฟล์ที่ไม่เกี่ยวข้องออกไป


คุณพูดถูกฉันไม่ได้ใส่นามสกุลหลังจากแฟล็ก -i เป็น-i''อันตรายไม่ว่าด้วยเหตุผลใด ๆ นอกจากอาจทำให้ไฟล์ต้นฉบับเสียหาย (และไม่มีการสำรองข้อมูล)
อาทิตย์

ตามsedหน้า man ถ้าคุณใช้พื้นที่ดิสก์บนอุปกรณ์คุณอาจเสียหายไฟล์ mid-stride และมีผลลัพธ์ที่ไม่ดี หากคุณกำลังทำงานภายใต้การควบคุมแหล่งท้องถิ่นsed -i ""โดยไม่มีการสำรองข้อมูลควรจะปรับเวลาส่วนใหญ่ (หรือgit init && git add -A . && git commit -m 'backup'ก่อนที่จะทำงานใน-iโหมดsed )
cfeduke

2
ฉันพบว่าบิตอันตรายเล็กน้อยที่มีประโยชน์โดยเฉพาะ +1
อังเดร

5
BSD sed ต้องการให้ไม่มีช่องว่างหลังจากแฟล็ก -i ดังนั้น-i''ถูกต้อง แต่-i ''ไม่ใช่
Todd A. Jacobs

3
โอ๊ะ! BSD ไม่สนใจอักขระ '\ n' และพิมพ์ 'n' แทน! ฉันจะแทนที่ BSD sed ด้วย GNU sed บน mac ของฉัน!
nterry

20

ฉันมีปัญหาคล้ายกันกับ MacOS

sed -i '' 's/oldword/newword/' file1.txt

ใช้งานไม่ได้ แต่

sed -i"any_symbol" 's/oldword/newword/' file1.txt

ทำได้ดี.


นี่คือวิธีอื่นในขณะนี้ sed -i '' <file>ทำงานได้ แต่sed -i'' <file>ไม่ทำงานอีกต่อไป
Zohaib Amanzai


4

คุณสามารถใช้-i''( --in-place) สำหรับsedตามที่แนะนำไว้แล้ว ดู: ในสถานที่โต้แย้งแต่ทราบว่าตัวเลือกที่เป็นส่วนขยายของ FreeBSD ที่ไม่ได้มาตรฐานและอาจไม่สามารถใช้ได้ในระบบปฏิบัติการอื่น ๆ ประการที่สองคือS tream ED Itor ไม่แก้ไขไฟล์-i-ised


ทางเลือกอื่นคือใช้การทดแทนในตัวในโหมด Vim Ex เช่น:

$ ex +%s/foo/bar/g -scwq file.txt

และสำหรับหลายไฟล์:

$ ex +'bufdo!%s/foo/bar/g' -scxa *.*

หากต้องการแก้ไขไฟล์ทั้งหมดซ้ำคุณสามารถใช้**/*.*หากเชลล์รองรับ (เปิดใช้งานโดยshopt -s globstar)


อีกวิธีหนึ่งคือการใช้gawkและส่วนขยาย "inplace"ใหม่เช่น:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1

4

สิ่งนี้จะสร้างไฟล์สำรอง เช่นsed -i -e 's/hello/hello world/' testfileสำหรับฉันสร้างไฟล์สำรองข้อมูล testfile-e ใน dir เดียวกัน


เหมือนกันที่นี่กับ Mac OS Catalina การส่งผ่านทั้ง -i และ -e แยกกัน (ไม่ใช่ -i ร่วมกัน!) จะสร้างไฟล์สำรองข้อมูลที่มี '-e' ต่อท้าย
Daniel Kesner

1

คุณสามารถใช้ได้:

sed -i -e 's/<string-to-find>/<string-to-replace>/' <your-file-path>

ตัวอย่าง:

sed -i -e 's/Hello/Bye/' file.txt

นี้ทำงานได้อย่างไร้ที่ติในMac


2
สิ่งนี้จะสร้างไฟล์สำรองสำหรับฉันใน Mac OS Catalina โดยใช้ '-e' ผนวก
Daniel Kesner

สิ่งนี้ผิดสำหรับ macOS โปรดดูที่หน้า "คนใจเย็น" ที่นั่น -iต้องการอาร์กิวเมนต์สำหรับ macOS เนื่องจากคุณไม่ได้ระบุไว้ไฟล์นั้นจะใช้-eซึ่งจะทำให้มีไฟล์ที่สอง-eต่อท้าย -eไม่อยู่ใน MacOS -Eมันเป็น คำสั่งที่ถูกต้องสำหรับ macOS คือsed -i '' -E 's/Hello/Bye/' file.txt
Marc J. Schmidt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.