正则断言-先行断言先行否定断言
?=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" 或完全没有点字符。