regex - sed regex 在第一场比赛时停止

标签 regex perl sed phpbb

我想替换以下 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=...] 标记中的第一个和最后一个匹配项之间。我似乎无法让它替换行中这种模式的每一次出现......(我不认为有任何嵌套的引号,但这会使它变得更加困难)

最佳答案

您需要使用与 Perl 兼容的正则表达式的 sed(1) 版本,以便您可以执行诸如进行最小匹配或负前瞻之类的操作。

最简单的方法就是首先使用 Perl。

如果您有现有的 sed 脚本,则可以使用 s2p(1) 实用程序将其转换为 Perl。请注意,在 Perl 中,您确实想使用 $1右侧s///运算符(operator)。在大多数情况下,\1是祖父,但总的来说你想要$1那里:

s/<blockquote.*?written by (.*?)<\/i>/[quote=$1]/g;

注意我已经删除了括号前面的反斜杠。使用 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使其将标准输入、标准输出和文件视为 UTF-8。 -00让它一口气读完整个文件,/s根据需要使点跨越换行符边界。

关于regex - sed regex 在第一场比赛时停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10964455/

相关文章:

mysql - perl 中 DBD 和 mysql 的问题

linux - perl 中的 '\b' 字符是如何工作的?

linux - 如何在linux下正确使用sed

linux - 如何使用 sed 只显示一行中的某些单词?

c++ - 如何使用 boost spirit 找到 n 次出现的表达式?

javascript - 每行至少搜索2个字母的正则表达式

java - 字符串 "Slot-Extraction"

regex - 有没有一种简单的方法可以在Excel中替换占位符?

regex - 在Perl中,如何匹配两个连续的回车符?

regex - Linux bash 脚本 - 替换文件中最后一次出现的字符串