4

У меня есть ряд файлов 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 пока он работает!

3 ответа3

9

Я бы использовал 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
1

Это можно сделать с помощью 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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .