ฉันจะแทนที่หลายบรรทัดด้วยคำเดียวในไฟล์ (แทนที่แทนที่) ได้อย่างไร


9

เนื้อหาของfilenameไฟล์ของฉันเป็นดังต่อไปนี้ (ตัวอย่าง):

My block of line starts from here 
START
First line
second line
third line
END
and end to here for example.

ฉันต้องการที่จะแทนที่บล็อกเส้นระหว่างSTARTและมีเพียงคำเดียวเช่นกับEND SINGLEWORDชอบด้านล่าง:

My block of line starts from here 
SINGLEWORD
and end to here for example.

ฉันสามารถหาบล็อกของบรรทัดด้วยการใช้คำสั่งนี้:

grep -Pzo "START(.|\n)*END" filename

และผลลัพธ์ของการรันคำสั่งด้านบนจะเป็นดังนี้:

START
First line
second line
third line
END

จากนั้นฉันใช้คำสั่งนี้เพื่อรวมบรรทัดทั้งหมดเป็นบรรทัดเดียว:

LAST_RESULT | sed -e :a -e '/$/N; s/\n/ /; ta'

จากนั้นฉันจะได้รับผลลัพธ์นี้:

START First line second line third line END

และด้วยคำสั่งสุดท้ายของLAST_RESULTS | sed 's/.*/SINGLEWORD/'ฉันฉันเปลี่ยนพวกเขาเป็น"SINGLEWORD"และฉันได้รับผลนี้

SINGLEWORD

ตอนนี้สิ่งที่ฉันต้องการคือ: ฉันจะใช้คำสั่งนี้ (หรือคำสั่งข้อเสนอแนะของคุณ) และแทนที่ (ในสถานที่) บล็อกบรรทัดของฉันเป็นคำ "SINGLEWORD" ได้อย่างไร และผลลัพธ์สุดท้ายจะเป็นเช่นนี้ไฟล์:

My block of line starts from here 
SINGLEWORD
and end to here for example.

คำตอบ:


14

สามารถทำได้อย่างง่ายดายในperl:

$ perl -i -p0e 's/START.*?END/SINGLEWORD/s' file
$ cat file
My block of line starts from here 
SINGLEWORD
and end to here for example. 

คำอธิบาย

-0 ตั้งตัวคั่นบรรทัดเป็นโมฆะ

-pใช้สคริปต์ที่กำหนดโดย-eให้กับแต่ละบรรทัดและพิมพ์บรรทัดนั้น

ตัวดัดแปลง regexp:

  • /sถือว่าสตริงเป็นบรรทัดเดียว นั่นคือเปลี่ยน.เพื่อให้ตรงกับตัวละครใด ๆ แม้แต่ขึ้นบรรทัดใหม่ซึ่งตามปกติมันจะไม่ตรงกัน

ทำไม?:

  • โดยค่าเริ่มต้นรูปแบบย่อยที่ถูกจัดอันดับคือ "โลภ" นั่นคือมันจะจับคู่หลาย ๆ ครั้งให้มากที่สุดเท่าที่จะเป็นไปได้ ?หากคุณต้องการให้ตรงกับจำนวนขั้นต่ำครั้งที่เป็นไปได้ทำตามปริมาณที่มี

@KasiyA: การใช้sedควรจะเป็นไปได้ แต่อาจจะอ่านยากกว่านี้ (ดูคำถามนี้)
Sylvain Pineau

หนึ่งมากขึ้นเพราะเริ่มต้นและสิ้นสุดของฉันมีรูปแบบตัวอักษรพิเศษ ( /, *, ?) ในนั้นและเหล่านี้เป็นเพียงตัวอย่าง และคุณสามารถอธิบายคำสั่งของคุณได้ไหม
αғsнιη

@KasiyA คุณสามารถหลบหนีตัวละครดังกล่าวกับ \ (ตรงตามที่มีsed): \/, \*,\?
Sylvain Pineau

@KasiyA perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'ฉันพยายาม ควรใช้งานได้
Sylvain Pineau

@KasiyA ฉันคิดว่าฉันทำตอนนี้พร้อมคำอธิบายแล้ว)
Sylvain Pineau

14

ผมสงสัยว่าถ้าเป็นไปได้โดยไม่ต้องperl, pythonและอื่น ๆ และฉันพบวิธีแก้ปัญหานี้โดยใช้sed:

$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename

คำอธิบาย:

  1. : a สร้างป้ายกำกับ 'a'
  2. ยังไม่มีการ ผนวกบรรทัดถัดไปกับพื้นที่รูปแบบ
  3. $! ถ้าไม่ใช่บรรทัดสุดท้าย , ba สาขา (ไปที่) ป้ายกำกับ 'a'
  4. s แทน , /START.*END/โดยSINGLEWORD, / g การแข่งขันทั่วโลก (หลายครั้งตามที่มันสามารถ)

มันถูกพบที่นี่

@KasiyA ขอบคุณฉันเรียนรู้สิ่งที่น่าสนใจมากมาย!

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