Содержание моего 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
Теперь то, что я хочу: Как я могу использовать эту команду (Или Вашу команду предложения) и замена (на месте) мой блок строк к слову "ОДНОСЛОВНОМУ"? И конечный результат будет похож на этот файл:
My block of line starts from here
SINGLEWORD
and end to here for example.
Это может быть сделано очень легко в 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
строка Обработки как одна строка. Таким образом, изменитесь .
для соответствия любому символу вообще, даже новая строка, которой обычно он не соответствовал бы. , Почему ?
:
?
. Я задавался вопросом, возможно ли это без perl
, python
и другие. И я нашел это решение с помощью sed
:
$ sed ':a;N;$!ba;s/START.*END/SINGLEWORD/g' filename
Объяснение:
/START.*END/
SINGLEWORD
, /g глобальное соответствие (как много раз, как это может) , Это было найдено здесь .
@KasiyA, спасибо я изучил много интересных вещей!
Хотя ripgrep
специально не поддерживает встроенную замену, я обнаружил, что его текущая функциональность --replace
уже полезна для этот вариант использования:
rg --replace 'SINGLEWORD' --passthru --no-line-number \
--multiline --multiline-dotall 'START.*?END' input.txt > output.txt
Объяснение:
--replace 'SINGLEWORD'
включает режим замены и устанавливает строку замены. Можно включить захваченные группы регулярных выражений, используя $1
и т. д. --passthru
необходим, поскольку ripgrep
обычно показывает только строки, соответствующие шаблону регулярного выражения. С этой опцией он также показывает все строки из файла, которые не совпадают. --no-line-number / -N
потому, что по умолчанию ripgrep
включает номера строк в вывод (полезно, когда отображаются только совпадающие строки). --multiline / -U
включил многострочную обработку, поскольку по умолчанию она отключена. --multiline-dotall
требуется только в том случае, если вы хотите, чтобы шаблон регулярного выражения с точкой ('.') соответствовал новой строке (\n
). > output.txt
необходим, так как встроенная замена не поддерживается. С опциями --passthrough
и no-line-number
стандартный вывод соответствует желаемому новому файлу с заменами и может быть сохранен как обычно. Однако эта команда не так полезна для обработки нескольких файлов, так как ее нужно запускать отдельно для каждого файла.