Skip to content
📈0️⃣

正则断言-先行断言先行否定断言

?=pattern 是先行断言,?!pattern 是先行否定断言。它们在正则表达式中用于在匹配位置上进行条件限制,而不会真正消耗匹配的字符。

先行断言 (?=pattern)

  • 它会对当前位置后面的内容进行匹配。
  • 只有当紧随当前位置的内容满足 pattern 时,才会继续往下匹配。

例如,正则表达式 /abc(?=def)/ 匹配 "abcdef" 中的 "abc",因为 "abc" 后面紧跟着 "def"。

js
'abcdef'.replace(/abc(?=def)/, '-') // abcdef --> '-def'
'abcabc'.replace(/abc(?=def)/, '-') // abcabc --> 'abcabc'
'abc.md'.replace(/.+(?=\.md)/, '-') // abc.md --> '-.md'

先行否定断言 (?!pattern)

  • 它会对当前位置后面的内容进行匹配。
  • 只有当紧随当前位置的内容不满足 pattern 时,才会继续往下匹配。

例如,正则表达式 /abc(?!def)/ 匹配 "abcklm" 中的 "abc",因为 "abc" 后面不是 "def"。

js
'abcdef'.replace(/abc(?!def)/, '-') // abcdef --> 'abcdef'
'abcabc'.replace(/abc(?!def)/, '-') // abcabc --> '-abc'
'abc.md'.replace(/.+(?!\.md)/g, '-') // abc.md --> '-'
// 以上结果的原因是: '.+' 匹配 'abc.md' --> 'abc.md' 后面是空而不是 '.md' --> 'abc.md' 满足条件被替换成 '-'
'abc.md'.replace(/.*(?=\.)(?!\.md)/, '-') // 'abc.md'
/**
 * 以上结果的原因是: 
 * '.+' 匹配 'abc.md'
 * (?=\.) 表面上匹配到了 abc. , 但是因为先行断言不消耗字符串, 实际匹配到的是 abc
 * (?!\.md) 匹配不是以 .md 结尾的字符, abc 恰好以 .md 结尾, 所以不满足条件, 不会被替换
 * 最终结果是 'abc.md' --> 'abc.md'
 */

在你的情况中,^(?=.*\.md$)(?!.*\.)[^.]+$ 中的 (?=.*\.md$) 是一个先行断言,用于确保字符串中存在 ".md" 并且是结尾处;(?!.*\.) 则是一个先行否定断言,用于确保字符串中不存在任何点字符。这两个断言结合起来,可以实现你所描述的需求,即必须包含 ".md" 或完全没有点字符。