我有一系列包含如下两行内容的 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
但它不起作用。我怀疑它卡在了新线路上,我不知道如何解决这个问题。
sed
任何帮助都值得感激。只要它能用,请随意推荐其他 Linux 工具!
答案1
我会使用 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
答案2
sed
无法直接匹配多行。当需要多行模式时,请使用更强大的工具,例如 Perl:
perl -i~ -ne 'if (/^<h1>Title/) {
$n = <>;
if ($n =~ /<br>$/) { print "Replacement\n" }
else { print "$_$n" }
} else { print }'
答案3
这可以用 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