Как заменить несколько строк одним словом в файле (заменить на месте)?

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.
αғsнιη
источник

Ответы:

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для каждой строки и распечатать эту строку

Модификатор регулярного выражения:

  • /sОбрабатывать строку как одну строку. То есть измените, .чтобы соответствовать любому символу, даже символу новой строки, который обычно не соответствует.

Почему ?:

  • По умолчанию квантифицированный подшаблон является «жадным», то есть он будет совпадать столько раз, сколько это возможно (учитывая конкретное начальное местоположение), при этом оставаясь сопоставимым с остальной частью шаблона. Если вы хотите, чтобы он совпадал с минимально возможным числом раз, следуйте квантификатору с помощью ?.
Сильвен Пино
источник
@KasiyA: Использование sedдолжно быть возможным, но, вероятно, труднее для чтения (посмотрите на этот вопрос )
Сильвен Пино,
Еще один , потому что мой START и END модель имеет специальные символы ( /, *, ?) в нем , и это просто пример. и не могли бы вы объяснить свою команду.
αғsнιη
@KasiyA вы можете избежать таких символов с \ (точно так , как с sed): \/, \*,\?
Сильвен Pineau
@KasiyA Я пытался perl -i -p0e 's/\/\*.*?\*\//SINGLEWORD/sm'. Это должно сработать
Сильвен Пино
@KasiyA Я думаю, что я закончил с объяснениями сейчас;)
Сильвен Пино
14

Мне было интересно , если это возможно без perl, pythonи другие. И я нашел это решение, используя sed:

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

Объяснение:

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

Это было найдено здесь .

@KasiyA, спасибо, я узнал много интересного!

c0rp
источник