Skip to content

Latest commit

 

History

History
25 lines (16 loc) · 3.5 KB

023-匹配整行字符.md

File metadata and controls

25 lines (16 loc) · 3.5 KB

在做正则匹配的时候,有时候我们想找到匹配结果所处的行,而不是仅仅包含匹配结果。例如在文本编辑器中,我们搜索包含单词 John 所在的行,并将改行删除。

行中包含指定单词

在上面这个例子中我们可以使用表达式John来匹配字符 John ,但是匹配结果仅包含 john ,而不是 john 所在的一整行。

解决方法很简单。我们可以使用位置字符^$去匹配行的开始和结束,并且需要开启多行模式匹配(在JavaScript中多行模式是m)来匹配文件内部的换行符。接下来我们要匹配字符串中除了 john 以外的部分,这里可以使用.*,表达式为:^.*John.*$

行中包含任意一个指定单词

如果要匹配的字符有多种可能,我们可以使用选择符。例如表达式^.*\b(one|two|three)\b.*$可以匹配包含单词 one、two、three 中任意一个的行。这个表达式中的回溯引用将保存实际匹配到的单词。如果这行数据包含多个符合条件的单词,那么回溯引用会捕获最靠右的单词,这是因为星号*贪婪的。如果使用了非贪婪匹配,例如^.*?\b(one|two|three)\b.*$,那么回溯引用将捕获最靠左的单词。

确保一行中同时包含多个单词

如果要在一行中同时匹配多个单词,我们可以使用预测断言。表达式^(?=.*?\bone\b)(?=.*?\btwo\b)(?=.*?\bthree\b).*$可以匹配文本中完整的一行,并且其中同时包含三个单词 one、two、three。这个表达式中的位置字符会匹配一行的开始和结束。并且由于脱字符^和预测断言都是零宽的,所以三个预测断言都会从一行的开头开始匹配。在每一个预测断言内部.*?会匹配目标单词之前的所有字符,并且三个预测断言必须全部匹配成功,整个表达式才能匹配成功。实际上我们可以在预测断言中使用任何表达式去实现更复杂的匹配。在三个预测断言匹配成功之后,我们使用.*$确保匹配结果是一个完整的行。

确保一行中不包含指定单词

如果你的匹配条件是:一行中不包含某些单词,那么应该使用负预测断言。表达式^((?!regexp).)*$可以匹配一行完整的字符串,并且字符串中不包含regexp。注意,这里和正预测断言不同,我同时对负预测和句号使用了量词。这是因为使用正预测的时候我们只要确保字符串中至少包含一个指定的单词,而负预测要确保字符串的每一个位置都不包含指定的单词。所以我们要对字符串的每个位置进行测试,以确保每个位置都不能匹配regexp

确保一行字符串包含一组单词,并且不包含另一组

最后,你也可以把前两种匹配条件组合在一起使用:^(?=.*?\bmust-have\b)(?=.*?\bmandatory\b)((?!avoid|illegal).)*$。在这个表达式中前两个正预测可以保证字符串中包含指定的单词,第三个负预测可以确保匹配结果是完整的一行,并且不包含指定的单词。


如果文章出现错误,请给我提Issues - - Github地址

原文