JS regex positive look behind * 应该什么时候不贪心?
JS regex positive look behind * not greedy when it should?
如果我查看文档,它说 *
应该总是贪婪的,但在这种情况下它不是:
// returns 'password*****' instead of 'password: *****'
'password: "something"'.replace(/(?<=password[ :]*)[^\n,]+/i, '*****')
FROM TC39 DOCS lookbehind proposal
模式通常从最左边的子模式开始匹配,如果左边的子模式成功,则继续匹配右边的子模式。当包含在回顾断言中时,匹配的顺序将被颠倒。模式将从最右边的子模式开始匹配,然后向左推进。例如,给定 /(?<=$\d+\.)\d+/
,该模式将首先找到一个数字并首先确保它前面有 。向后移动,然后是 \d+ 从 . 开始,最后 $ 从断言中的 \d+ 开始。回溯方向也会因此反转。
因为你的 [^\n,]+
将匹配除 new line and ,
之外的所有字符,所以它也会捕获 :
并且你的后视不会看到它,因为它已经被后视后的断言捕获,
你可以做的是使用 +
这将确保你至少匹配 one space or :
'password: "something"'.replace(/(?<=password[ :]+)[^\n,]+/i, '*****')
处理回溯时,它首先搜索回溯之后的模式,在本例中为 [^\n,]+
。然后它测试lookbehind是否与该位置左侧的字符串部分匹配;如果匹配则匹配成功,否则重复,寻找主模式的下一个匹配。它不是从搜索后视开始的。
[^\n,]+
匹配您输入的每个子字符串。当它到达子字符串 <space>"something"
时,lookbehind 匹配,因为 [ ;]*
匹配一个空字符串。它不会继续尝试进一步匹配以使后向匹配具有更长的前缀。
@CodeManiac 的回答是正确的;但是,要进一步改进您的正则表达式,您可能需要这样做:
const regex = /(password[: ]+)([^\n,]+)/i;
const passwordStr = 'password: something';
console.log(passwordStr.replace(regex, '***********'))
有了这个,您基本上创建了 2 个匹配组:提示 (password:
) 和值 (something
)。然后将字符串替换为第一组 (</code> = <code>password:
),后跟星号。
如果我查看文档,它说 *
应该总是贪婪的,但在这种情况下它不是:
// returns 'password*****' instead of 'password: *****'
'password: "something"'.replace(/(?<=password[ :]*)[^\n,]+/i, '*****')
FROM TC39 DOCS
lookbehind proposal
模式通常从最左边的子模式开始匹配,如果左边的子模式成功,则继续匹配右边的子模式。当包含在回顾断言中时,匹配的顺序将被颠倒。模式将从最右边的子模式开始匹配,然后向左推进。例如,给定 /(?<=$\d+\.)\d+/
,该模式将首先找到一个数字并首先确保它前面有 。向后移动,然后是 \d+ 从 . 开始,最后 $ 从断言中的 \d+ 开始。回溯方向也会因此反转。
因为你的 [^\n,]+
将匹配除 new line and ,
之外的所有字符,所以它也会捕获 :
并且你的后视不会看到它,因为它已经被后视后的断言捕获,
你可以做的是使用 +
这将确保你至少匹配 one space or :
'password: "something"'.replace(/(?<=password[ :]+)[^\n,]+/i, '*****')
处理回溯时,它首先搜索回溯之后的模式,在本例中为 [^\n,]+
。然后它测试lookbehind是否与该位置左侧的字符串部分匹配;如果匹配则匹配成功,否则重复,寻找主模式的下一个匹配。它不是从搜索后视开始的。
[^\n,]+
匹配您输入的每个子字符串。当它到达子字符串 <space>"something"
时,lookbehind 匹配,因为 [ ;]*
匹配一个空字符串。它不会继续尝试进一步匹配以使后向匹配具有更长的前缀。
@CodeManiac 的回答是正确的;但是,要进一步改进您的正则表达式,您可能需要这样做:
const regex = /(password[: ]+)([^\n,]+)/i;
const passwordStr = 'password: something';
console.log(passwordStr.replace(regex, '***********'))
有了这个,您基本上创建了 2 个匹配组:提示 (password:
) 和值 (something
)。然后将字符串替换为第一组 (</code> = <code>password:
),后跟星号。