Як замінити кілька рядків одним словом у файлі (замінити замість)?


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

Ще один , тому що мій START і END модель має спеціальні символи ( /, *, ?) в ньому , і це просто приклад. і ви могли б пояснити свою команду.
αғsnιη

@KasiyA ви можете уникнути таких символів з \ (точно так , як з sed): \/, \*,\?
Сільвен Pineau

@KasiyA Я спробував perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'. Це має спрацювати
Сільвейн Пано

@KasiyA Я думаю, що зараз я закінчую поясненнями;)
Sylvain Pineau

14

Мені було цікаво , якщо це можливо без perl, pythonі інші. І я знайшов це рішення, використовуючи sed:

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

Пояснення:

  1. : a створити мітку "a"
  2. N додайте наступний рядок до простору візерунка
  3. $! якщо не останній рядок , ба гілка (перейти до) мітка "a"
  4. єва заміна , /START.*END/по SINGLEWORD, / г глобального матчу (стільки разів , скільки це можливо)

Це було знайдено тут .

@KasiyA, дякую, я дізнався багато цікавого!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.