我正在尝试构建一个匹配单个换行符(\n
)的正则表达式。
同样,我需要另一个正则表达式来匹配\n\n
不属于较长的换行符(如\n\n\n
or\n\n\n\n\n\n
等)的双换行符()。
\n(?!\n)
并且\n\n(?!\n)
匹配太多(它们匹配更长的换行序列中的最后一个换行符)。我能做些什么呢?
我正在尝试构建一个匹配单个换行符(\n
)的正则表达式。
同样,我需要另一个正则表达式来匹配\n\n
不属于较长的换行符(如\n\n\n
or\n\n\n\n\n\n
等)的双换行符()。
\n(?!\n)
并且\n\n(?!\n)
匹配太多(它们匹配更长的换行序列中的最后一个换行符)。我能做些什么呢?
由于 JavaScript 不支持后向断言,因此您需要在 n`s 之前匹配一个额外的字符并记住\
稍后处理它(即,如果您使用正则表达式匹配来修改原始字符串,则恢复它)。
(^|[^\n])\n(?!\n)
匹配单个换行符加上前面的字符,并且
(^|[^\n])\n{2}(?!\n)
匹配双换行符加上前面的字符。
因此,例如,如果您想用 a 替换单个,则必须\n
这样做<br />
result = subject.replace(/(^|[^\n])\n(?!\n)/g, "$1<br />");
对于\n\n
,是
result = subject.replace(/(^|[^\n])\n{2}(?!\n)/g, "$1<br />");
解释:
( # Match and capture in group number 1:
^ # Either the start of the string
| # or
[^\n] # any character except newline.
) # End of group 1. This submatch will be saved in $1.
\n{2} # Now match two newlines.
(?!\n) # Assert that the next character is not a newline.
所有与ECMAScript 2018兼容的 JavaScript 环境都支持后视。
因此,您可以使用
(?<!\n)\r?\n(?!\r?\n)
匹配单个 CRLF 或 LF libne 中断序列。如果您需要匹配两个换行符,请将\r?\n
使用模式部分包装在一个组中并为其设置一个量词:(?<!\n)(?:\r?\n){2}(?!\r?\n)
匹配一个双换行符序列。
详情:
(?<!\n)
- 如果在当前位置的左侧有一个 LF 字符,则匹配失败的负向后查找\r?\n
- 一个可选的 CR,然后是一个 LF 字符(?!\r?\n)
- 如果有一个可选的 CR,然后在当前位置的右侧紧接着一个 LF 字符,则匹配失败的负前瞻。请参阅 JavaScript 演示,展示如何替换段落内换行序列,即那些单行换行序列:
const text = "This\nis\nparagraph\none\n\nThis is the\nsecond\nparagraph";
console.log( text.replace(/(?<!\n)\r?\n(?!\r?\n)/g, "<br />") );
要精确匹配同一字符的 N 次重复,您需要前瞻和后视(请参阅精确匹配同一字符的 N 次重复)。由于 javascript 不支持后者,纯正则表达式解决方案似乎是不可能的。您必须使用辅助函数,例如:
> x = "...a...aa...aaa...aaaa...a...aa"
"...a...aa...aaa...aaaa...a...aa"
> x.replace(/a+/g, function($0) {
return $0.length == 2 ? '@@' : $0;
})
"...a...@@...aaa...aaaa...a...@@"