【问题标题】:Match character but not when preceded by匹配字符但不匹配
【发布时间】:2014-05-03 06:18:50
【问题描述】:

我想使用 JavaScript 替换所有换行符,但前提是它们前面没有这两个字符 {](两者,不是其中一个)。以下表达式似乎可以完成这项工作,但它破坏了其他正则表达式结果,所以一定有问题:

/[^\{\]]\n/g

我做错了什么?

【问题讨论】:

  • 当你说两者时,你的意思是{ ],或者你的意思是模式{]
  • 我的意思是字符串{],大概就是你说的模式的意思。
  • 尝试使用否定的lookbehind。
  • 是的..这就是我过去一个小时试图做的事情。
  • 谢谢@AmitJoki,但即使你没有明确表示你发布了一个,我也会看到你的答案和更新:)

标签: javascript regex regex-negation


【解决方案1】:

您是否需要能够去除\n\r\n,或两者兼而有之?

这应该可以完成工作:

/(^|^.|[^{].|.[^\]])\r?\n/gm

并且要求您将 $1 放在替换字符串的开头。

要回答您关于为什么/[^\{\]]\n/ 错误的问题,此正则表达式等同于:“匹配任何既不是{ 也不是] 的字符”,后跟\n,因此这错误地无法匹配以下内容:

here's a square]\n
see the following{\n

您还缺少最后的 g 标志,但您可能已经注意到了。

【讨论】:

  • 谢谢。将\n 替换为\r\n 还不够吗?
  • @ScepticalJule 是的,我想那样可以。
  • @JLRishe:为什么是^?这将在换行符之前选择(并替换)一个或两个字符。如果[^{][^\]] 失败,正则表达式引擎将移动到下一个字符并匹配]\n,而我们不希望这样。
  • @Robin 我有时仍然对“非捕获组”的含义感到困惑。我在上面进行了编辑以解决这个问题。 ^^. 用于说明在字符串的开头或第二个字符出现换行符的可能性。
  • @JLRishe:它在foo]\n 上失败,因为o 匹配[^{]][^\]] 不匹配...如果您像这样使用负前瞻:@ 987654343@ 我发现它是一个优雅的解决方案(即使可能不是最佳性能)。也不要忘记多行 m 标志。
【解决方案2】:

当您使用[^\{\]] 时,您使用的是字符范围:这代表“任何不是\{\] 的字符。这意味着匹配将在{\n}\n 上失败。

如果你想否定一个长于一个字符的模式,你需要一个否定的前瞻:

/^(?!.*{]\n)([^\n]*)\n/mg

^(?!          # from the beginning of the line (thanks to the m flag)
    .*{]\n    # negative lookahead condition: the line doesn't end with {]\n
)
([^\n]*)      # select, in capturing group 1, everything up to the line break
\n

然后替换为

$1 + replacement_for_\n

我们所做的是逐行检查我们的行不包含不需要的模式。

如果不是,我们在捕获组 1 中选择直到结尾 \n 的所有内容,并将整行替换为该所有内容,然后是您要替换 \n 的内容。

演示:http://regex101.com/r/nM2xE1

【讨论】:

    【解决方案3】:

    不支持向后看,你可以这样模拟

    stringWhereToReplaceNewlines.replace(/(.{0,2})\n/g, function(_, behind) {
      return (behind || "") + ((behind === '{]') ? "\n" : "NEWLINE_REPLACE")
    })
    

    每个“\n”都会调用回调,并将前面的 2 个字符作为第二个参数。回调必须返回替换“\n”和之前的 2 个字符的字符串。如果前面的 2 个字符是“{]”,那么新行不应该被替换,所以我们返回完全匹配的字符串,否则我们返回前面的 2 个字符(可能为空)和应该替换换行符的东西

    【讨论】:

      【解决方案4】:

      我的解决方案是这样的:

      ([^{].|.[^\]])\n
      

      你的替换字符串应该是$1<replacement>

      由于 JavaScript 不支持lookbehind,我们必须使用lookahead。这就是正则表达式的工作方式:

      • 除了{ 之外的任何东西 - [^{].
      • 或者任何东西,然后是] - .[^\]]
      • 简单地说,[^{].|.[^\]] 匹配除 {] 之外的所有 .. 匹配的内容
      • 最后一个\n

      \n 之前的两个字符被捕获,因此您可以使用 $1 将它们重新插入到替换字符串中。

      【讨论】:

      • 见@JLRishe 的回答:后面的想法是一样的,但你的解决方案不会匹配m\n 或孤独的\n(它不考虑没有两个字符的情况在\n 之前)。我也觉得这个想法很优雅,但不是很可扩展:如果禁止模式是 10 个字符长,你会怎么做?在我看来,前瞻解决方案会更容易适应。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-01
      • 2011-05-20
      • 2021-07-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-01
      • 1970-01-01
      相关资源
      最近更新 更多