我想替换以下html文本的一部分(大文件的摘录),以更新旧的论坛格式(由非常糟糕的论坛移植2年前完成的工作)到常规的phpBB格式:
<blockquote id="quote"><font size="1" face="Verdana, Arial, Helvetica" id="quote">quote:<hr height="1" noshade id="quote"><i>written by User</i>
这应该过滤成:
[quote=User]
我在sed中使用了以下正则表达式
s/<blockquote.*written by \(.*\)<\/i>/[quote=\1]/g
这适用于给定的示例,但在实际文件中,这样的几个引号可以在一行中。在这种情况下,sed太贪心,并将所有内容放在[quote = ...]标记中的第一个和最后一个匹配之间。我似乎无法让它取代行中这种模式的每一个出现...(我不认为有任何嵌套引号,但这会使它更加困难)
答案 0 :(得分:3)
你需要一个使用Perl兼容正则表达式的 sed (1)版本,以便你可以做一些事情,比如做一个最小的匹配,或者做一个负向前瞻的事情。
最简单的方法就是首先使用Perl。
如果您有现有的 sed 脚本,则可以使用 s2p (1)实用程序将其转换为Perl。请注意,在Perl中,您确实希望在$1
运算符的右侧使用s///
。在大多数情况下,\1
已经过时,但通常您需要$1
:
s/<blockquote.*?written by (.*?)<\/i>/[quote=$1]/g;
注意我已经删除了parens前面的反斜杠。使用Perl的另一个好处是它使用了理智的 egrep 式正则表达式(如 awk ),而不是丑陋的 grep 式(如 sed )需要所有那些令人困惑(和不一致)的反斜杠。
使用Perl的另一个好处是你可以使用配对的,可嵌套的分隔符来避免丑陋的反斜杠。例如:
s{<blockquote.*?written by (.*?)</i>}
{[quote=$1]}g;
其他优势包括Perl与UTF-8(现在是Web的大多数编码形式)相处得非常好,并且您可以进行多行匹配,而不会出现 sed 所需的极度痛苦。例如:
$ perl -CSD -00 -pe 's{<blockquote.*?written by (.*?)</i>}{[quote=$1]}gs' file1.utf8 file2.utf8 ...
-CSD
使得它将stdin,stdout和文件视为UTF-8。 -00
使其在一次啜饮中读取整个文件,并且/s
使点交叉换行边界。
答案 1 :(得分:1)
我认为sed
不支持非贪婪匹配。你可以试试perl:
perl -pe 's/<blockquote.*?written by \(.*\)<\/i>/[quote=\1]/g' filename
答案 2 :(得分:0)
这可能对您有用:
sed '/<blockquote.*written by .*<\/i>/!b;s/<blockquote/\n/g;s/\n[^\n]*written by \([^\n]*\)<\/i>/[quote=\1]/g;s/\n/\<blockquote/g' file
说明:
/<blockquote.*written by .*<\/i>/!b
s/<blockquote/\n/g
[^\n]*
代替.*
全局替换换行符,然后替换剩余的换行符。 s/\n[^\n]*written by \([^\n]*\)<\/i>/[quote=\1]/g
s/\n/\<blockquote/g