Вопрос: Подстановка многострочного шаблона в файл HTML


У меня есть ряд файлов HTML, которые содержат две строки:

<body>
<h1>Title</h1><p>
<a href="url">Description</a><br>

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

sed -i -r 's/<h1>Title.*?$\/^.*?<br>/Replacement text/1' filename.html

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

Любая помощь оценивается. Не стесняйтесь предлагать другие инструменты Linux, кроме sed пока это работает!


4
2018-05-19 17:01


Источник


Вам действительно нужно sed для этого? sed читает строки за строкой, поэтому замена многострочного текста немного утомительна. - slhck
Мне не нужно использовать sed. Я открыт для других команд Linux. - To Do
да, шаблон, пересекающий несколько строк, может быть проблемой для sed. - barlop


Ответы:


Я бы использовал Perl для этого:

perl -0pe 's/<h1>Title.*\n.*<br>/replacement/' filename.html

Вот, -0 делает записи на основе Perl NUL вместо чтения строки за строкой, которая является значением по умолчанию при использовании -p вариант.

С регулярными выражениями Perl вам нужно .*  для соответствия любому символу несколько раз, и вы сопоставляете новую строку с \n,

Пример:

$ echo '<body>
<h1>Title</h1><p>
<a href="url">Description</a><br>' | perl -0pe 's/<h1>Title.*\n.*<br>/replacement/'
<body>
replacement

9
2018-05-19 17:21



И не забывайте, никогда не использовать регулярные выражения для синтаксического анализа HTML! :) - terdon
Это почти хорошо. Я добавил? после двух. *, чтобы отключить жадность. Можно ли заставить команду изменить файл вместо вывода на STDOUT? - To Do
@ToDo Perl может выполнять редактирование на месте с помощью -i вариант, поэтому выполните perl -0p -i~ -e 's/…/…/' чтобы он редактировал исходный файл, создавая резервную копию с ~ как суффикс. Или, чтобы заменить файл без файла, вызовите perl -0pi -e …, - slhck


sed не может соответствовать более одной строке. Когда требуется многострочный шаблон, найдите более мощный инструмент, такой как Perl:

perl -i~ -ne 'if (/^<h1>Title/) {
                  $n = <>;
                  if ($n =~ /<br>$/) { print "Replacement\n" }
                  else { print "$_$n" }
              } else { print }'

1
2018-05-19 17:22





Это можно сделать с помощью sed.

sed -nf repl.sed filename.html

где repl.sed содержит:

# Must have one line loaded up before branching to rep.
# Processing will start this way.
:rep
# Load extra line into pattern space
N
# Test for title
/<h1>.*<\/h1><p>\n<a href=".*">.*<\/a><br>/{
  #Substitute and print
  s/<h1>\(.*\)<\/h1><p>\n<a href=".*">.*<\/a><br>/Title: \1/p
  #append next line without cycling
  N
  # everything but the last line
  s/.*\n\([.\n]*\)/\1/
  #test for last line
  ${
    p
    # this will effectively end the program
    n
  }
  b rep
}
${
  # will print pattern space (both lines)
  p
  # this will effectively end the program
  n
}
#Print first line in pattern space
P;
#Remove first line in pattern space with newline
s/.*\n\([.\n]*\)/\1/
b rep

Видеть Работа с несколькими строками


1
2017-07-03 21:04