ทดสอบการค้นหาแบบเรียกซ้ำและแทนที่ก่อนเรียกใช้


13

มีวิธีใดบ้างในการเรียกใช้การค้นหาแบบเรียกซ้ำและแทนที่โดยใช้sedก่อนที่จะเรียกใช้จริง ฉันแค่ต้องการพิมพ์ผลลัพธ์ก่อนทำการค้นหาและแทนที่จริง ๆ สิ่งที่ต้องการสะท้อนผลลัพธ์ของ

grep -rl term1 . |xargs sed -i -e 's/term1/term2/'

ทำสำเนาข้อมูลเรียกใช้คำสั่งของคุณตรวจสอบผลลัพธ์
Kusalananda

คำตอบ:


10

คุณสามารถรันได้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


น่าสนใจฉันพยายามค้นหาความหมายของ -i แต่มันไม่ได้อยู่ในรายชื่อของผู้ชาย โซลูชันของคุณใช้ได้ผล อะไรจะเป็นวิธีที่ดีที่สุดในความเห็นของคุณเพียงแค่เขียนบรรทัดไม่ใช่ไฟล์ทั้งหมด? แทนที่จะเป็นท่อให้น้อยลง grep term2 ซึ่งใช้งานได้ แต่ฉันได้ผลลัพธ์ด้วยตัวอักษรแปลก ๆ เช่นกัน
user251482

@ user251482 - "เพียงแค่แสดงรายการบรรทัด" เช่นเดียวกับใน "การดูความแตกต่างระหว่างไฟล์เก่าและใหม่"?
grebneke

1
@StephaneChazelas ใช่หรือดีกว่าgrep -rl --nullเนื่องจาก OP ไม่ได้ระบุระบบปฏิบัติการและ-Zหมายถึงบางสิ่งที่แตกต่างใน BSD / OSX (คลายการบีบอัด) --nullเหมือนกันทั้งใน GNU และ BSD
grebneke

1
@grebneke จุดที่ดี แต่โปรดทราบว่า OP กำลังใช้ไวยากรณ์ของ GNU sed ดังนั้นเราจึงสามารถสรุปได้ว่าเขาไม่ได้อยู่ใน BSD โปรดทราบว่าgrepเป็น (ทางแยก) GNU grep บน FreeBSD และ NetBSD บน NetBSD -Zยังคงหมายถึง--null(ตามหน้า man) แต่ฉันเห็นด้วย - ไม่มีอะไรเป็นแบบพกพามากขึ้น นอกจากนี้โปรดทราบว่า --null หรือ -Z ไม่ทำงานบน OpenBSD
Stéphane Chazelas

1
@grebneke sed -i '' -e s/.../อยู่ใน BSD sed(ไม่มีตัวเลือกเพิ่มเติม)
Stéphane Chazelas

5

ใช้sedกับfindแทนgrep

ก่อนอื่นฉันจะจ้างfindมากกว่าgrepนี้และด้วยเหตุผลสามประการที่ดี:

  1. findช่วยให้การเลือกไฟล์ที่แม่นยำยิ่งขึ้น ตัวอย่างเช่นgrep -r string *.txtจะให้ไฟล์ในไดเรกทอรีปัจจุบันเท่านั้น ไม่ได้อยู่ในไดเรกทอรีย่อย
  2. findมาพร้อมกับ-execตัวเลือกที่มีประสิทธิภาพซึ่งไม่จำเป็นต้อง--null … |xargs 0สร้างทั้งหมด
  3. -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ตัวอย่างเพิ่มเติม

เพิ่มเติมfindตัวอย่างสามารถพบได้ที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.