【问题标题】:JS regex positive look behind * not greedy when it should?JS regex 正面看后面 * 什么时候不贪心呢?
【发布时间】:2019-09-10 15:39:02
【问题描述】:

如果我查看文档,它说* 应该总是贪婪,但在这种情况下它不是:

// returns 'password*****' instead of 'password: *****'
'password: "something"'.replace(/(?<=password[ :]*)[^\n,]+/i, '*****') 

【问题讨论】:

  • lookbehinds 通常不允许使用量词。
  • @Barmar 在 chrome 中编译正常,没有任何错误,有什么原因吗?
  • 抱歉,显然 EcmaScript 允许这样做。

标签: javascript regex ecmascript-6 lookbehind


【解决方案1】:

来自 TC39 文档lookbehind proposal

模式通常从最左边的子模式开始匹配,如果左边的子模式成功则移动到右边的子模式。当包含在后向断言中时,匹配的顺序将被颠倒。模式将从最右边的子模式开始匹配,然后向左前进。例如,给定/(?&lt;=\$\d+\.)\d+/,该模式将首先找到一个数字并首先确保它前面是 .往回走,然后是 \d+ 从 . 开始,最后是 $ 从断言中的 \d+ 开始的地方开始。回溯的方向也会因此而反转。


由于您的[^\n,]+ 将匹配除new line and , 之外的所有字符,因此它还将捕获:,并且您的后视将看不到它,因为它已被后视后的断言捕获,

您可以做的是使用+,这将确保您至少匹配one space or :

'password: "something"'.replace(/(?&lt;=password[ :]+)[^\n,]+/i, '*****') 

【讨论】:

  • +1 我正要说这个,但没能及时找到参考。由于看起来总是有一个冒号和空格,因此最好执行[ :]{2,}之类的操作
  • @Toto firefox 还不支持lookebhinds
  • 所以不能在生产环境中使用
  • @Toto 不,除非您使用某种具有跨浏览器支持这些功能的库xregexp
【解决方案2】:

@CodeManiac 的回答是正确的;但是,为了进一步改进您的正则表达式,您可能需要执行以下操作:

const regex = /(password[: ]+)([^\n,]+)/i;
const passwordStr = 'password: something';

console.log(passwordStr.replace(regex, '$1***********'))

有了这个,基本上您正在创建 2 个匹配组:提示 (password:) 和值 (something)。然后将字符串替换为第一组 ($1 = password:),后跟星号。

【讨论】:

    【解决方案3】:

    当处理一个lookbehind 时,它首先在lookbehind 之后搜索模式,在本例中为[^\n,]+。然后它测试后向是否匹配该位置左侧的字符串部分;如果匹配,则匹配成功,否则重复,寻找主模式的下一个匹配项。它不是从寻找后视开始的。

    [^\n,]+ 匹配输入中的每个子字符串。当它到达子字符串&lt;space&gt;"something" 时,后向匹配,因为[ ;]* 匹配一个空字符串。它不会继续尝试进一步的匹配以使后向匹配更长的前缀。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-23
      • 2020-03-15
      • 2018-03-07
      • 2021-11-11
      • 1970-01-01
      • 2012-04-27
      • 2012-09-08
      相关资源
      最近更新 更多