มีวิธีใดบ้างในการเรียกใช้การค้นหาแบบเรียกซ้ำและแทนที่โดยใช้sedก่อนที่จะเรียกใช้จริง ฉันแค่ต้องการพิมพ์ผลลัพธ์ก่อนทำการค้นหาและแทนที่จริง ๆ สิ่งที่ต้องการสะท้อนผลลัพธ์ของ
grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
มีวิธีใดบ้างในการเรียกใช้การค้นหาแบบเรียกซ้ำและแทนที่โดยใช้sedก่อนที่จะเรียกใช้จริง ฉันแค่ต้องการพิมพ์ผลลัพธ์ก่อนทำการค้นหาและแทนที่จริง ๆ สิ่งที่ต้องการสะท้อนผลลัพธ์ของ
grep -rl term1 . |xargs sed -i -e 's/term1/term2/'
คำตอบ:
คุณสามารถรันได้sedโดยไม่ต้อง-iผ่านขั้นตอนเอาต์พุตด้วยless
grep -rl --null term1 . | xargs -0 sed -e 's/term1/term2/' | less
จากนั้นเรียกใช้sedด้วย-i.bakเพื่อสร้างการสำรองข้อมูลซึ่งคุณสามารถแตกต่างกันในภายหลัง
grep -rl --null term1 . | xargs -0 sed -i.bak -e 's/term1/term2/'
diff somefile.bak somefile
# verify changes were correct
แก้ไข:grep --null | xargs -0เป็นข้อเสนอแนะในการแสดงความคิดเห็นการใช้งาน สิ่งนี้ทำให้ชื่อไฟล์ถูกยกเลิกโดย null-byte ซึ่งทำให้ปลอดภัยสำหรับชื่อไฟล์ที่มีอักขระผิดปกติเช่นขึ้นบรรทัดใหม่ ใช่\nเป็นอักขระที่ถูกต้องในชื่อไฟล์ยูนิกซ์ อักขระต้องห้ามเท่านั้นคือslash /และอักขระ nul\0
grep -rl --nullเนื่องจาก OP ไม่ได้ระบุระบบปฏิบัติการและ-Zหมายถึงบางสิ่งที่แตกต่างใน BSD / OSX (คลายการบีบอัด) --nullเหมือนกันทั้งใน GNU และ BSD
grepเป็น (ทางแยก) GNU grep บน FreeBSD และ NetBSD บน NetBSD -Zยังคงหมายถึง--null(ตามหน้า man) แต่ฉันเห็นด้วย - ไม่มีอะไรเป็นแบบพกพามากขึ้น นอกจากนี้โปรดทราบว่า --null หรือ -Z ไม่ทำงานบน OpenBSD
sed -i '' -e s/.../อยู่ใน BSD sed(ไม่มีตัวเลือกเพิ่มเติม)
sedกับfindแทนgrepก่อนอื่นฉันจะจ้างfindมากกว่าgrepนี้และด้วยเหตุผลสามประการที่ดี:
findช่วยให้การเลือกไฟล์ที่แม่นยำยิ่งขึ้น ตัวอย่างเช่นgrep -r string *.txtจะให้ไฟล์ในไดเรกทอรีปัจจุบันเท่านั้น ไม่ได้อยู่ในไดเรกทอรีย่อยfindมาพร้อมกับ-execตัวเลือกที่มีประสิทธิภาพซึ่งไม่จำเป็นต้อง--null … |xargs 0สร้างทั้งหมด-readableและ-writableตัวเลือกของfindจะป้องกันไม่ให้เสียเวลาในไฟล์ที่ไม่สามารถเข้าถึงได้ที่กล่าวว่าgrepจะให้ยืมตัวสำหรับการทดสอบครั้งแรกเพื่อดูสิ่งที่จะถูกจับ:
$ find . -exec grep term1 {} \;
หรือเฉพาะเจาะจงมากขึ้น:
$ find . -type f -name '*.txt' -readable -writable -exec grep term1 {} \;
ตอนนี้ดำเนินการต่อด้วยการsedแห้ง sedตัวเลือก-nเป็นคำพ้องหา--quietและpที่ปลายสุดของsedการแสดงออกจะพิมพ์พื้นที่รูปแบบปัจจุบัน
$ find . -exec sed -n 's/term1/term2/gp' {} \;
หรือเฉพาะเจาะจงมากขึ้น:
$ find . -type f -name '*.txt' -readable -writable -exec sed -n 's/term1/term2/gp' {} \;
หากทุกอย่างดูดีออกคำสั่งที่ชัดเจนโดยการเปลี่ยนตัวsedเลือก-nโดย-iสำหรับ "ในสถานที่" และโดยการลบpในตอนท้าย
$ find . -exec sed -i 's/term1/term2/g' {} \;
หรือเฉพาะเจาะจงมากขึ้น:
$ find . -type f -name '*.txt' -readable -writable -exec sed -i 's/term1/term2/g' {} \;
findตัวอย่างเพิ่มเติม