【问题标题】:How can I remove certain characters from inside angle-brackets, leaving the characters outside alone?如何从尖括号内删除某些字符,将字符单独留在外面?
【发布时间】:2011-02-18 12:05:36
【问题描述】:

编辑:为了清楚起见,请理解我没有使用正则表达式来解析 html,这太疯狂了!我只是想清理一个凌乱的 html 字符串,以便它解析

编辑 #2:我还应该指出,我使用的控制字符是一个特殊的 unicode 字符 - 在任何正常情况下,它都不会在适当的标签中使用

假设我有一个包含一堆控制字符的 html 字符串,我想只从标签内部删除控制字符,只留下标签外部的字符。

例如

这里的控制字符是数字“1”。

输入

The quick 1<strong>orange</strong> lemming <sp11a1n 1class1='jumpe111r'11>jumps over</span> 1the idle 1frog

所需的输出

The quick 1<strong>orange</strong> lemming <span class='jumper'>jumps over</span> 1the idle 1frog

到目前为止,我可以匹配包含控制字符的标签,但我无法在一个正则表达式中删除它们。我想我可以在我的比赛中执行另一个正则表达式,但我真的很想知道是否有更好的方法。

我的正则表达式

请记住,这仅匹配包含控制字符的标签。

<(([^>])*?`([^>])*?)*?>

非常感谢您的时间和考虑。

伊恩·弗雷泽

【问题讨论】:

  • 再次声明显而易见的......stackoverflow.com/questions/1732348/…
  • 是的,是的,是的,我知道,我知道。但我没有解析 html。当人们在同一个句子中看到 html 和 regex 时,他们会立即得出结论。在这种情况下,碰巧我正在使用 html,但这个问题可能适用于任何类型的字符串:“我想删除 '!' 的所有实例大括号之间的字符”。这是同一类问题 - 字符串的实际含义无关紧要。
  • 为了记录,未处理的字符串甚至可能不会解析为 html(例如,如果控制字符落在标签名称内)。这就是为什么我想从标签内部删除它们。
  • 作为建议,我会更改您的问题以描述您遇到的问题。不要决定你想要的方式。没有理由假设正则表达式是您需要的解决方案。如果您除了展示您对解决方案的尝试之外没有提及正则表达式,那么人们可以从不同的角度看待问题。
  • 注明。我知道 html/regex 是一个敏感的主题,是的,我想仅仅因为我决定使用 regex 并不意味着其他人会这样做。我只是想要一个可以在一行中编写的解决方案,这就是为什么正则表达式让我觉得它是正确的工具

标签: html regex string replace


【解决方案1】:

Regex 不是用于此目的的工具,但您可以使用lookbehind 和lookahead 来匹配标签中的1。这是在 Java 中,修改为具有有限的后视(因为 Java 不支持无限长的后视)。

    String s = "123 <o123o></o1o1> <oo 11='11x'> x11 <msg136='I <3 Johnny!11'>";
    System.out.println(
        s.replaceAll("(?<=<[^<>]{0,999})(?=[^<>]+>)1", "")
    ); // prints "123 <o23o></oo> <oo ='x'> x11 <msg136='I <3 Johnny!'>

在很多情况下这会失败,但它应该能让你从某个地方开始。

另见


好的,我已经“概括”了这个问题,使它与 HTML 无关。这是一个 Java 的 sn-p,它使用正则表达式从 &lt;&gt; 包围的句子部分中删除 [aeiou],其用途仅用于标记这些特殊部分。

注意:这个正则表达式绝对不可读。但是,是的,它有效。而且它也不使用后视。

String s = "Wait <whaaat?> does this <really really> work???";
System.out.println(
    s.replaceAll("(?!>)(?:(?=<)|(?=\\G)(?!^))(?:(?:(?![aeiou])(.))|.)", "$1")
); // prints "Wait <wht?> does this <rlly rlly> work???"

如果有兴趣,我可能尝试解释一下,否则我建议使用这样的简单循环:

allocate output buffer
set isInside := false
for every character ch in input
   if (ch is openChar)
      isInside := true
   else if (ch is closeChar)
      isInside := false
   else if not (isInside and ch is control)
      append ch to buffer

【讨论】:

  • 只是出于兴趣,您认为合适的工具是什么?我只使用正则表达式,因为我要删除的内容有一个非常明确的模式:即“从尖括号中删除所有控制字符”。我还应该指出,我的实际控制字符不会出现在任何有效的 html 标记中。
  • @Iain:如果你能保证属性值中永远不会有&lt;&gt;,那么我认为正则表达式是可以的。否则,您将无法平衡引号、处理转义序列等,而且我认为它会变得很冒险。如果 &lt;&gt; 仅保留用于打开和关闭标签,那么这很简单。
  • 感谢 polygenelubricants 的建议 - 顺便说一下,您的原始正则表达式运行良好。我不愿意使用解析引擎是因为您可能无法获得有效的开始和结束标签——它们可能不一致。这是可能的,例如:&lt;1strong&gt;Hey, I1'm in bold!&lt;/strong&gt;
【解决方案2】:

我知道您并没有像这样“解析”它。但是,您确实需要弄清楚什么是 html 标签,什么不是,这需要解析并且单独使用正则表达式无法解决这个问题。

也许标签名称中控制字符的解决方案是用有效的文本模式全局替换所有控制字符。

然后您可以使用 xml/html 文档解析器解析生成的 xml/html。然后,您可以运行它以对标记名、属性名称、值执行搜索和替换。

【讨论】:

    【解决方案3】:

    您通常不应该使用正则表达式来解析 html - 但这不是 html 开头,因此您不能使用解析器。以下似乎有效。

    var s = "The quick 1<strong>orange</strong> lemming <sp11a1n 1class1='jumpe111r'11>jumps over</span> 1the idle 1frog";
    while(s.match(/<[^>]*?1(?=[^>]*>)/))
      s = s.replace(/(<[^>]*?)1(?=[^>]*>)/g, "$1");
    console.log(s); //"The quick 1<strong>orange</strong> lemming <span class='jumper'>jumps over</span> 1the idle 1frog"
    

    【讨论】:

    • 感谢您理解 Amarghosh - 这个想法是我想清理一个字符串,以便它有合理的机会解析为 html...
    猜你喜欢
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 1970-01-01
    • 2013-08-14
    相关资源
    最近更新 更多