#regex #linux #unix #replace
#регулярное выражение #linux #unix #заменить
Вопрос:
Я ищу способ поиска и замены по нескольким строкам с помощью сценария оболочки. Это то, что я пытаюсь сделать:
source:
[stuff before]
<!--WIERD_SPECIAL_COMMENT_BEGIN-->
[stuff here, possibly multiple lines.
<!--WIERD_SPECIAL_COMMENT_END-->
[stuff after]
target:
[stuff before]
[new content]
[stuff after]
Короче говоря, я хочу удалить комментарии и все, что между ними, и заменить каким-нибудь новым контентом. В принципе, я хочу выполнить простую команду sed в нескольких строках и, если возможно, просто использовать некоторые базовые инструменты * nix, без дополнительного языка сценариев.
Ответ №1:
Если вам нужно сопоставить только полные строки, вы можете выполнить эту задачу с awk
помощью . Что-то вроде:
awk -v NEWTEXT=foo 'BEGIN{n=0} /COMMENT_BEGIN/ {n=1} {if (n==0) {print $0}} /COMMENT_END/ {print NEWTEXT; n=0}' < myfile.txt
Если файл не так хорошо отформатирован, с комментариями в
той же строке, что и текст, который вы хотите сохранить или удалить, я
бы использовал perl
, прочитал весь файл в одну строку,
выполнил сопоставление с регулярным выражением и заменил эту строку, затем записал новую строку в
новый файл. Это не так просто, и вам нужно написать perl
скрипт для выполнения этой работы.
Что-то вроде:
#!/usr/bin/perl
$newtext = "foonbar";
$/ = ''; # no input separator so whole file is read.
$s = <>; # read whole file from stdin
$startPattern = quotemeta('<!--WIERD_SPECIAL_COMMENT_BEGIN-->');
$endPattern = quotemeta('<!--WIERD_SPECIAL_COMMENT_END-->');
$pattern = $startPattern . '. ' . $endPattern;
$s =~ s/$pattern/$newtext/sg;
print $s;
Комментарии:
1. мой файл довольно прост, так что это должно сработать. из любопытства, есть ли какой-нибудь базовый инструмент unix, который может сделать это за меня, если я не могу использовать строки, или мне нужно что-то более мощное?
2. Я думаю, что это слишком сложно для
sed
или других базовых инструментов UNIX. Я добавил пример вperl
— я думаю, что это самое простое возможное решение, когда оно не работает построчно.
Ответ №2:
sed
делает это просто отлично. Следующее настолько просто, насколько это возможно; если вам нужно извлечь данные из строки-разделителя перед начальным разделителем или после конечного разделителя, это будет немного сложнее.
sed '/<!--WIERD_SPECIAL_COMMENT_BEGIN-->/,/<!--WIERD_SPECIAL_COMMENT_END-->/d' input >output
Если у вас есть какой-либо контроль над этим, исправьте написание «странно».
Ответ №3:
другое решение… это можно сделать в однострочном формате, но с использованием регулярных выражений perl, с которыми мне легче работать, чем с sed или awk (которые громоздки при многострочном сопоставлении и замене):
perl -0 -i -pe 's/<!--WIERD_SPECIAL_COMMENT_BEGIN-->[sS]*<!--WIERD_SPECIAL_COMMENT_END-->/your new content here/gim' yourfile1.txt
обратите внимание, что при этом файл будет заменен новым, измененным содержимым.