Как использовать sed для замены всех строк между двумя совпадающими шаблонами (в OSX BSD)

Я хотел бы знать, как:

  • Замените все строки между двумя совпадающими шаблонами (не включая шаблоны - эксклюзивно). Обратите внимание, что они будут на отдельных строках.

  • Замените все строки между двумя совпадающими шаблонами и включая их (включительно). Обратите внимание, что они будут в отдельных строках. Я начал первым, но это не дало желаемых результатов (на самом деле пока никаких результатов). Имейте в виду, что это для sed на Mac OSX (BSD). Шаблон в этом случае представляет собой два HTML-комментария в отдельных строках.

Мой сценарий оболочки выглядит так:

REPLACEWITH="Replacement text here"
sed -i '' -e "s&\(<!--BeginNotes-->\).*\(<!--EndNotes-->\)&\1$REPLACEWITH\2&" /Users/BlaNameHere/builds/development/index.php

В заголовке моего файла index.php есть этот отрывок:

<!--BeginNotes-->
    <!--asdasd-->
    <script type="application/javascript">var Jaop;</script>
<!--EndNotes-->

пример результата а

<!DOCTYPE html>
<html>
    <head>
        <title></title>
        <!--BeginNotes-->
        Replacement text here
        <!--EndNotes-->
    </head>
    <body>

    </body>
</html>

пример результата b

<!DOCTYPE html>
<html>
    <head>
        <title></title>
Replacement text here
    </head>
    <body>

    </body>
</html>

person vsiege    schedule 07.01.2014    source источник
comment
Вы привязаны к sed или разрешаете другие инструменты (например, awk)?   -  person glenn jackman    schedule 08.01.2014
comment
Я был бы не против увидеть решение awk, на данный момент я больше всего знаком с sed. Я также хотел бы остаться верным названию.   -  person vsiege    schedule 08.01.2014
comment
Как вы хотите, чтобы файл выглядел после операции?   -  person Beta    schedule 08.01.2014
comment
Я добавлю к вышесказанному, чтобы показать примеры файлов a и b   -  person vsiege    schedule 08.01.2014


Ответы (2)


Perl однострочник:

perl -i -0777 -pe 's/(<!--BeginNotes-->).*(<!--EndNotes-->)/$1'"$REPLACEWITH"'$2/s' index.php

При этом используется параметр -0777 для чтения всего файла как одной строки, для чего требуется модификатор s в команде s///s.

Этот однострочник примерно эквивалентен

perl -e '
    # read the file as a single string
    open $in, "<", "index.php";
    my $text;
    {
        local $/; 
        $text = <$in>;
    }
    close $in;

    # transform the string
    $text =~ s/(<!--BeginNotes-->).*(<!--EndNotes-->)/$1'"${REPLACEWITH}"'$2/s;

    # write out the new string
    open $out, ">", "index.php.tmp";
    print $out $text;
    close $out;

    # over-write the original file
    rename "index.php.tmp", "index.php"; 
'
person glenn jackman    schedule 07.01.2014

sed -n ":b
$ !{
   N
   b b
   }
$ {
   s|\(<!--BeginNotes-->\).*\(\n\)\([[:blank:]]*\)\(<!--EndNotes-->\)|\1\2\3${REPLACEWITH}\2\3\4|
   p
   }" /Users/BlaNameHere/builds/development/index.php

Вам нужно загрузить файл в буфер, потому что sed работает построчно

person NeronLeVelu    schedule 08.01.2014