แทนที่สตริงหลายบรรทัดในไฟล์


17

ฉันมีไฟล์จำนวนหนึ่งที่ฉันต้องการอัปเดตโดยแทนที่สตริงหลายบรรทัดหนึ่งด้วยสตริงอื่นหลายบรรทัด บางสิ่งบางอย่างตาม:

* Some text, 
* something else
* another thing

และฉันต้องการแทนที่ด้วย:

* This is completely
* different text

ผลที่ตามมาก็คือหลังจากการแทนที่ไฟล์ที่มีบล็อกแรกของข้อความตอนนี้จะมีสตริงที่สอง (ส่วนที่เหลือของไฟล์ไม่เปลี่ยนแปลง)

ส่วนหนึ่งของปัญหาคือฉันต้องค้นหารายชื่อไฟล์ที่จะอัพเดทในระบบไฟล์ ฉันเดาว่าฉันสามารถใช้ grep สำหรับสิ่งนั้นได้ (แม้ว่าจะไม่ใช่เรื่องง่ายที่จะทำกับสตริงหลายบรรทัด) จากนั้นลองใช้ greid หรือไม่?

มีวิธีง่าย ๆ ในการทำเช่นนี้? Sed เป็นตัวเลือก แต่มันน่าอึดอัดใจเพราะฉันต้องเพิ่ม \ n ฯลฯ มีวิธีที่จะพูดว่า "รับอินพุตจากไฟล์นี้จับคู่กับไฟล์เหล่านั้นจากนั้นแทนที่ด้วยเนื้อหาของไฟล์อื่นนี้" หรือไม่? ฉันสามารถใช้ python ถ้าจำเป็น แต่ฉันต้องการบางสิ่งที่รวดเร็วและง่ายดายดังนั้นหากมียูทิลิตีที่มีอยู่ฉันอยากจะใช้สิ่งนั้นมากกว่าเขียนสคริปต์ของตัวเอง (ซึ่งฉันรู้วิธีการทำ)


คุณน่าจะใช้ Perl สำหรับสิ่งนี้ stackoverflow.com/questions/1030787/…
orion

3
ดังนั้นคุณต้องการจับคู่some text, something else another thingว่ามีหลายบรรทัดหรือไม่ หรือคุณต้องการจับคู่some text,\nsomething else\nanotherthingเท่านั้น
mikeserv

2
แก้ไขคำถามของคุณและชี้แจงสิ่งที่เป็นเนื้อหาของแต่ละไฟล์และสิ่งที่ผลลัพธ์ที่ต้องการคืออะไร
jimmij

สตริงขยายหลายบรรทัด ฉันไม่สนใจช่องว่างเมื่อจับคู่ / แทนที่เพราะมันอาจจะไม่เหมือนกันทั้งหมด แต่ก็ไม่ใช่เรื่องใหญ่หากฉันทำ 1-1 แมทช์ (ขึ้นบรรทัดใหม่และทั้งหมด)
ventsyv

คำตอบ:


12

แทน "บางส่วน ... \ n ... สิ่ง" โดยเนื้อหาของไฟล์ "ใหม่" ในไฟล์อินพุตหนึ่งไฟล์หรือมากกว่า

perl -i -p0e 's/Some.*?thing\n/`cat new`/se' input.txt ...
  1. -i เพื่อเปลี่ยน input.txt โดยตรง
  2. -p0 slurp ไฟล์อินพุตไฟล์และพิมพ์ในท้ายที่สุด
  3. s/regexp/.../s ใน regexp .คือ.|\n
  4. s/.../exp/e แทนที่ด้วย eval(exp)
  5. ใหม่ - ไฟล์ที่มีข้อความแทนที่ (นี่คือข้อความที่แตกต่าง ... ทั้งหมด)
  6. ถ้ามีประโยชน์คุณสามารถขยายข้อความต้นฉบับได้ s/Some text\n...\n...thing\n/...

ฉันจะทำเช่นเดียวกันกับไฟล์ที่ชื่อว่า "ก่อน" เพื่อค้นหาเนื้อหา (หลายบรรทัด) ของไฟล์นั้นได้อย่างไร ฉันพยายาม แต่มันไม่ทำงาน
Kvothe

@Kvothe เราต้องการรายละเอียดเพิ่มเติม ... สมมติว่า "ก่อนหน้า" ไม่มีตัวอักษรพิเศษคุณสามารถลองperl -i -p0e ' $b= `cat before`; s/$b/Some thing\n/se' input.txt ...
JJoao

และสมมติว่า "ก่อน" มีอักขระพิเศษทั้งหมด (บรรทัดใหม่, เครื่องหมายทับ, วงเล็บ) ยกเว้น 'และ'
Kvothe

5
sed -e :n -e '$!N;/\n.*\n/!{$!bn
};  s/some text,\n* *something else\n* *another thing/this is completely\
different text/;P;D' <infile

ฉันกลัวว่าคุณจะมีช่วงเวลาที่ยากลำบากในการหาทางแก้ปัญหาที่เหมาะกับคุณจนกว่าคุณจะอธิบายปัญหาอย่างเป็นรูปธรรม - แต่นั่นเป็นสิ่งที่ QA เหมาะสมที่สุดสำหรับฉันอย่างที่เห็น บางทีนี่อาจจะทำให้คุณมีความคิด - มันจะเก็บ 3 บรรทัดในพื้นที่รูปแบบในแต่ละครั้ง - ด้วย lookahead 2 บรรทัด - ในขณะที่เลื่อนไปข้างหน้าผ่านไฟล์อินพุตเพียงหนึ่งบรรทัดในแต่ละครั้ง

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


0

ไม่แข็งแรง (เพราะอย่าเลือกสองสาย แต่ง่ายต่อการชำระ) และสามารถเป็นคอมไพเลอร์แบบ posix ไม่ได้ แต่ง่ายมาก:

sed '/^Some text/{:1;/another thing$/!{N;b 1}
     s/.*/this is completely\ndifferent text/g}' input.txt

คำสั่งแรกเพิ่มบรรทัดจากข้อความบางข้อความจนกระทั่งได้พบสิ่งอื่นจากนั้นบรรทัดที่สองจะเปลี่ยนเป็นข้อความอื่น

หมายเหตุข้อ จำกัด คือข้อความบางอย่างควรตามด้วยสิ่งอื่นเสมอ


ปัญหาคือสตริงอาจมีมากกว่า 2 บรรทัด (มากถึงหนึ่งโหลหรือมากกว่านั้น) และอาจมีสิ่งอื่น ๆ ที่อาจต้องหลีกเลี่ยงเช่นแท็บ * ฯลฯ
ventsyv

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