javascript - Javascript 正则表达式:无法删除多行字符串中的前瞻组中的前导空格
问题描述
我正在尝试使用正则表达式^(?<=[\s]*namespace[\s]*---+\s+)(.|\s)+(?=\(\s*\d+\s*rows\))/gm
从单列表格列表格式字符串中提取行项目。但是在匹配中添加了前导空格。lookahead 和lookbehind 组中的\s+
运算符没有帮助。参考以下:
x = `namespace
-------------------
itm1
itm2
itm3
itm4
(4 rows)
`
console.log(x.match(/^(?<=[\s]*namespace[\s]*---+\s+)(.|\s)+(?=\(\s*\d+\s*rows\))/gm)[0].split(/\s+/))
输出带有前导和尾随空格作为单独的列表元素:
[ '', 'itm1', 'itm2', 'itm3', 'itm4', '' ]
但是使用console.log(x.match(/^(?<=[\s]*namespace[\s]*---+\s+)(.|\s)+(?=\(\s*\d+\s*rows\))/gm)[0].trim().split(/\s+/))
<-- 注意 trim()
之前的split(..)
,输出是:
[ 'itm1', 'itm2', 'itm3', 'itm4' ]
为什么\s+
前瞻组末尾的(?<=[\s]*namespace[\s]*---+\s+)
不会删除 . 捕获的所需匹配组之前的所有空格(.|\s)+
。
解决方案
根本原因
正则表达式引擎从左到右解析字符串。
正则表达式在字符串的开头搜索匹配,但没有找到后向模式,它在那里失败,然后测试下一个位置,在n
和a
之间namespace
。依此类推,直到-------------------
.
在换行符之后的位置\n
,有一个lookbehind模式匹配,\s+
在lookbehind的末尾找到\s+
pattern所需的空格。然后,模式的其余部分也会找到匹配项。因此,您的结果中有 15 个前导空格。
解决方案
使用消费模式。也就是说,使用捕获组。或者,确保您的消费部分以非空白字符开头。
因此,
const x = "namespace\n-------------------\n itm1\n itm2\n itm3\n itm4\n \n(4 rows)\n";
console.log(
x.match(/(?<=^\s*namespace\s*---+\s+)\S.*?(?=\s*\(\s*\d+\s*rows\))/gms)[0].split(/\s+/)
);
或者,使用捕获组:
const x = "namespace\n-------------------\n itm1\n itm2\n itm3\n itm4\n \n(4 rows)\n";
console.log(
x.match(/^\s*namespace\s*---+\s+(\S.*?)(?=\s*\(\s*\d+\s*rows\))/ms)[1].split(/\s+/)
);
注意正则表达式:
- 我
(.|\s)+
用一个简单的.
模式替换,但添加了s
标志,以便.
可以匹配换行符。请永远不要使用(.|\s)*
,(.|\n)*
或(.|[\r\n])*
, 这些是非常低效的正则表达式模式 - 我
\s*
在正向前瞻的开头添加了,以便可以从匹配中删除尾随空格。 - 我还在两种模式中都使用了一个惰性点 ,
.*?
来匹配两个字符串之间的最少字符数。
推荐阅读
- python - 使用 Python 3.7.4 安装 Pyarrow 时出错
- ruby-on-rails - 查询以从 Rails 上的关联模型中获取所有数据
- javascript - 在 WordPress 中将动态内容标题拆分为两种颜色
- c++ - 关于静态常量数据成员的声明和定义的困惑
- node.js - 带有 HTML 的电子邮件进入垃圾邮件
- python - Python阻止键盘写入
- firebase - 从特定应用程序发送 FCM 的云功能
- java - 对 TreeMap 中键入的数字字符串进行排序
- vue.js - 删除索引 0 处的组件删除所有项目
- python - GAE 超出了实例内存限制。超过 2,048 个月?