วิธีการแทนที่รหัสหลายบรรทัดด้วย sed


9

ฉันมีไฟล์ขนาดใหญ่ที่มีอักขระพิเศษอยู่ sedมีรหัสหลายคู่สายจะมีที่ฉันต้องการจะเปลี่ยน

นี้:

  text = "\
    ------                                                           ------\n\n\
    This message was automatically generated by email software\n\
    The delivery of your message has not been affected.\n\n\
    ------                                                           ------\n\n"

จำเป็นต้องเปลี่ยนเป็น:

text = ""

ฉันลองใช้รหัสต่อไปนี้ แต่ไม่มีโชค:

sed -i '/  text = "*/ {N; s/  text = .*affected.\./  text = ""/g}' /etc/exim.conf

มันไม่ได้แทนที่อะไรและไม่แสดงข้อความผิดพลาดใด ๆ

ฉันเล่นกับมันมาแล้ว แต่ทุกอย่างที่ฉันลองทำไม่ทำงาน


มันจำเป็นต้องเป็นsedหรือคุณเปิดให้กับเครื่องมืออื่น ๆ หรือไม่? จะมี"ข้างในtext=บล็อกได้ไหม? อาจมีกรณีอื่น ๆtext = ในไฟล์ของคุณหรือไม่? จะมีข้อความ 4 บรรทัดหรือจะมากหรือน้อย?
terdon

โดยเฉพาะอย่างยิ่งsedหรืออะไรก็ตามที่ไม่จำเป็นต้องติดตั้งในเซิร์ฟเวอร์ CentOS ออกจากกล่องเครื่องมือ
blade19899

@terdon ไม่มีอื่น ๆในโฟลเดอร์ออกมาตอบสนองความต้องการที่จะเป็นtext = text = ""ไฟล์มีรหัส 891 บรรทัด ดังนั้นจึงต้องเคารพข้อความอื่น ๆ ด้วย
blade19899

คุณต้องการเขียนทับไฟล์หรือเพียงแค่ปรับเปลี่ยนผลลัพธ์?
joH1

@ Moonstroke ไม่มากเกินไป เป็นเพียงความต้องการที่จะเปลี่ยนข้อความ - เท่าที่เห็นในคำถามของฉัน - text = ""เพื่อ ตามที่เห็นในคำถามของฉัน
blade19899

คำตอบ:


15

Perl เพื่อช่วยเหลือ:

perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
  • -i~ จะแก้ไขไฟล์ "ในตำแหน่ง" โดยปล่อยสำเนาสำรองไว้
  • -0777 อ่านไฟล์ทั้งหมดในครั้งเดียวไม่ใช่ทีละบรรทัด

การทดแทนจะs///ทำงานคล้าย ๆ กับใน sed (นั่นคือจับคู่text = "แล้วตามด้วยอะไรก็ได้ แต่มีเครื่องหมายคำพูดสองเท่าหลายครั้งจนถึงเครื่องหมายคำพูดคู่) แต่ในกรณีนี้มันใช้ได้กับไฟล์ทั้งหมด


5

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

sed '/text = "/{              # if line matches text = "
:b                            # label b
$!N                           # pull in the next line (if not the last one)
/"$/!bb                       # if pattern space doesn't end with " go to label b
s/".*"/""/                    # else remove everything between the quotes
}' infile

กับgnu sedคุณสามารถเขียนมันเป็น

sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile

นั่นไม่ได้มีประสิทธิภาพมากนักเพียงแค่เลือกช่วง/text = "/,/"/ปรับเปลี่ยนบรรทัดแรกและลบส่วนที่เหลือ:

sed '/text = "/,/"/{            # in this range
/text = "/!d                    # delete all lines not matching text = "
s/\\/"/                         # replace the backslash with quotes (this is only
}' infile                       # executed if the previous d wasn't executed)

อีกครั้งโดยgnu sedคุณสามารถเขียนเป็นหนึ่งซับได้:

sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile

3

ส่วนตัวฉันจะทำเช่นนี้ใน Perl หากเราสามารถสรุปได้ว่าไม่มี"ก่อนการปิด"คุณสามารถทำได้:

perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file

-0slurps ไฟล์ทั้งหมดอ่านลงในหน่วยความจำ -pหมายถึง "พิมพ์ทุกบรรทัด (ที่นี่เป็น 'เส้น' จะเป็นไฟล์ทั้งหมด) หลังจากใช้สคริปต์ที่กำหนดโดย-e" สคริปต์นั้นเป็นตัวดำเนินการทดแทนอย่างง่าย มันจะจับสตริงtextตามด้วย 0 หรือมากกว่าช่องว่างตัวละครเป็น=คนและ 0 หรือมากกว่าช่องว่างอีกครั้ง ( text\s*=\s*) $1และบันทึกเป็น จากนั้นก็จะเข้ามาแทนที่รูปแบบการจับเช่นเดียวกับสายยกที่สั้นที่สุดจะพบกับรูปแบบ ( $1) ""และ sธงทำให้.การขึ้นบรรทัดใหม่การแข่งขัน


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

@glennjackman argh! ฉันมักจะสับสน . perl -00ne 'print;exit'ซึ่งเป็นเหตุผลที่จริงผมสองครั้งการตรวจสอบโดยการเพิ่มวรรคพิเศษและการทำงาน และฉันยังคงใส่ผิดในคำตอบของฉัน! ขอบคุณคงตอนนี้
terdon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.