Замените начало каждой строки возможного многострочного шаблона

#perl #substitution

#perl #замена

Вопрос:

Я пытаюсь сопоставить многострочный шаблон и изменить каждую строку, соответствующую этому шаблону, включая первую, так, чтобы символ был добавлен в начале строки ( /- )

Например, у меня есть это :

 stuff above
<span>one-liner span</span>
stuff middle
    <span>stuff inside
    other stuff
    </span>
stuff below
  

И я хочу получить это :

 stuff above
  <span>one-liner span</span>
stuff middle
      <span>stuff inside
      other stuff
      </span>
stuff below
  

Пока я там :

 perl -n0e 's/n(.*<span style="color: green".*?</span>)/ $1/g amp;amp; print' myfile.html
  

Проблема здесь в том, что он изменяет только первую строку, и если это многострочный шаблон, я хочу изменить все строки.

Есть идеи, как это сделать?

Я использую perl, но я открыт для других инструментов, если вы считаете, что это лучше.

Спасибо!

Комментарии:

1. » измените каждую строку, включая первую » — но ваш образец » хотите получить » этого не делает? Вы имеете в виду префикс всех строк внутри <span> элемента в частности?

2. Да, это то, что я имел в виду, я исправлю свой вопрос

3. Чтобы обрабатывать скаляр (предположительно с символами новой строки в нем) как «действительно» многострочную строку, вам нужен /m модификатор, чтобы привязки начала и конца строки соответствовали всем переводам строк (а не только началу и концу строки). Вы часто также хотите, /s с которым . также совпадает новая строка. Однако необходимость сопоставления только внутри части строки (внутри span и т.д.) Сделает этот подход более сложным

Ответ №1:

Один из способов — использовать оператор диапазона

 perl -wpe'print "  " if /^s*<span/ .. /</span>/' file
  

.. Оператор при этом использовании сохраняет свое состояние, так что

Как только левый операнд становится истинным, оператор диапазона остается истинным до тех пор, пока правый операнд не станет истинным, после чего оператор диапазона снова становится ложным.

Его типичное использование заключается именно в выборе диапазона строк, ограниченного заданными условиями.

Здесь я ограничил открывающие span строки, чтобы они были первыми непустыми в своей строке, но не закрывающими, чтобы обеспечить работу однострочных <span ...>word</span> разделов.

Комментарии:

1. Это приятно. Я должен добавить одно требование, о котором я не упоминал ранее. <span>.*</span>nnstuffn</span> Тег может быть только однострочным. Я думаю, что ваш код не подходит для меня в этой ситуации, потому что это также будет верно для чего-то вроде: . Я соответствующим образом отредактирую свой вопрос, извините.

2. @ogr Ты имеешь в виду, что на одной строке может быть <span ...>red</span> ? Если это так, все, что потребовалось, это удалить ^ в состоянии закрытия, так что </span> это не обязательно должно быть на отдельной строке. Я добавил такую однострочку span вместе с еще несколькими строками к вашему образцу, и это работает.

3. Да, теперь, кажется, это сработало, спасибо! (Я все еще новичок в perl)

4. @ogr Отлично. Дайте мне знать о вопросах и / или, если что-то появится позже 🙂

Ответ №2:

Используйте оператор range, чтобы замаскировать нужный диапазон, а затем добавить к строкам, начинающимся с пробела. Этот код не дает именно того, что вы хотите, но укажет вам правильное направление.

 while(<>) {
    if( /stuff above/ .. /stuff below/ ){
        $_= " ".$_ if /^  /;
        print $_;
    }
}
  

Оператор диапазона — один из моих любимых!

Ответ №3:

если ваши данные в файле ‘d’

 perl -ne 'if (/^s*<(span)>.*?(</1>)?s*$/) {print " $amp;";next if ($2);$t="</$1>";do{$_=<>;print " $_"} until(/$t/) } else {print}' d
  

gnu sed

 sed -E 's/<(span)>.*</1>/ amp;/;Tc;b ;:c /^s*<span>/{s/^/ /;:l n;s/^/ /;/</span>/!bl}' d