正则表达式查找字符串中最后一次出现的模式
Regex to find last occurrence of pattern in a string
我的字符串形式为:
"as.asd.sd fdsfs. dfsd d.sdfsd. sdfsdf sd .COM"
我只想匹配最后一个句号(.)之前的最后一段空白
到目前为止,我能够捕获空格,但不能捕获 very 最后一次使用:
\s+(?=\.\w)
如何让它不那么贪心?
在一般情况下,您可以使用以下方案匹配最后一次出现的任何模式:
pattern(?![\s\S]*pattern)
(?s)pattern(?!.*pattern)
pattern(?!(?s:.*)pattern)
其中 [\s\S]*
尽可能多地匹配任意零个或多个字符。 (?s)
和 (?s:.)
可以与支持这些结构的正则表达式引擎一起使用,以便使用 .
匹配任何字符。
在这种情况下,而不是\s+(?![\s\S]*\s)
,您可以使用
\s+(?!\S*\s)
见regex demo。注意 \s
和 \S
是相反的 类,因此,这里使用 [\s\S]*
是没有意义的, \S*
就足够了。
详情:
\s+
- 一个或多个空白字符
(?!\S*\s)
- 后面没有紧跟任何 0 个或更多 non-whitespace 个字符,然后是一个空格。
你可以这样试试:
(\s+)(?=\.[^.]+$)
(?=\.[^.]+$)
正向预测一个点和除行尾点以外的字符。
演示:
你可以试试这个。它将捕获第一个捕获组中的最后一个白色 space 段。
(\s+)\.[^\.]*$
"as.asd.sd ffindMyLastOccurrencedsfs. dfindMyLastOccurrencefsd d.sdfsd. sdfsdf sd ..COM"
.*(?=((?<=\S)\s+)).*
replaced by `><`
> <
作为一个更普遍的例子
此示例定义了多个针并查找其中任何一个的最后一次出现。在这个例子中,针是:
- 定义词
findMyLastOccurrence
- 空格
(?<=\S)\s+
- 点
(?<=[^\.])\.+
"as.asd.sd ffindMyLastOccurrencedsfs. dfindMyLastOccurrencefsd d.sdfsd. sdfsdf sd ..COM"
.*(?=(findMyLastOccurrence|(?<=\S)\s+|(?<=[^\.])\.+)).*
replaced by `><`
>..<
解释:
第 1 部分 .*
- 贪心,只要找到针头什么都找。因此,它还会捕获所有出现的针,直到最后一根针。
编辑添加:
- 如果我们对第一个命中感兴趣,我们可以通过编写
.*?
来防止贪婪
第 2 部分 (?=(findMyLastOccurrence|(?<=\S)\s+|(?<=[^\.])\.+|(?<=**Not**NeedlePart)NeedlePart+))
- 定义贪心'find-all'的'break'条件。它由几个部分组成:
(?=(needles))
- positive lookahead:确保之前找到的everything之后是针
findMyLastOccurrence|(?<=\S)\s+|(?<=[^\.])\.+)|(?<=**Not**NeedlePart)NeedlePart+
- 我们正在寻找的几根针。针本身就是图案。
- 如果我们寻找一组空白、点或其他针刺部分,我们正在寻找的图案实际上是:任何 不是 一个针部分,后跟一个或多个针部分(因此针部分为+)。请参阅用 \S, actual dot 否定空格 \s 的示例。用 [^.]
否定
第 3 部分 .*
- 因为我们对其余部分不感兴趣,所以我们捕获它并且不再使用它。我们可以用括号捕获它并将其用作另一个组,但这超出了这里的范围
常见问题的简单解决方案
我通读的所有答案都偏离主题、过于复杂或根本不正确。这个问题是一个常见的问题,正则表达式提供了一个简单的解决方案。
分解一般问题
字符串
- 普遍的问题是有一个 string 包含几个字符。
SUB-STRING
- 在字符串中是由几个字符组成的sub-string。通常这是文件扩展名(即
.c
、.ts
或 .json
)或顶级域(即 .com
、.org
或 .io
),但它可以像 MC Donald's Mulan Szechuan Sauce
一样随意。关键是,它可能并不总是那么简单。
方差之前(最重要的部分)
- before variance 是一个或多个任意字符,总是出现在 sub-string 之前。在这道题中,之前的方差是一个未知数white-space。这是一个差异,因为需要匹配的 white-space 的数量会变化(或具有动态数量)。
参考问题描述解决方案
(解决方案第 1 部分)
通常在使用正则表达式时需要反向工作。
我们将从上述问题的末尾开始,往后做;我们将从 The Before Variance(或 #3)
开始
所以,如上所述,之前的方差是white-space的未知数。我们知道它包括 white-space,但我们不知道有多少,所以我们将使用 元序列用于 Any Whitespce 和 一个或多个量词.
“任何空白”的元序列是 \s
。
“一个或多个”量词是+
所以我们将从...开始...
注意:在 ECMAS Regex 中,/
字符就像字符串周围的引号。
const regex = /\s+/g
我还包含了 g
来告诉引擎将全局标志设置为 true。为了简洁起见,我不会解释标志,但是如果你不知道全局标志的作用,你应该去DuckDuckGo。
(解决方案第 2 部分)
请记住,我们正在反向工作,因此下一个要关注的部分是 Sub-string。在这个问题中它是.com
,但作者可能希望它匹配一个具有方差的值,而不仅仅是静态字符串.com
,因此我将在下面详细讨论,但是保持专注,我们现在将与 .com
合作。
我们有必要在这里使用一个概念,叫做零长度断言。我们需要一个“zero-length 断言”,因为我们有一个重要的 sub-string,但不是我们想要匹配的。 “Zero-length 断言”允许我们移动正则表达式引擎正在查看的字符串中的点,而无需匹配任何字符即可到达那里。
我们要用到的Zero-Length断言叫做LOOK AHEAD,语法如下。
Look-ahead 语法:(?=Your-SubStr-Here)
我们将使用前瞻性来匹配分配给 look-ahead 的模式之前出现的方差,这将是我们的 sub-string。结果如下所示:
const regex = /\s+(?=\.com)/gi
我添加了 insensitive 标志来告诉引擎不关心字母的大小写,换句话说;正则表达式 /\s+(?=\.cOM)/gi
与 /\s+(?=\.Com)/gi
相同,两者都与:/\s+(?=\.com)/gi
&/or /\s+(?=.COM)/gi 相同。只要设置了 i
标志,“刚刚列出”的每个正则表达式都是等效的。
就是这样! The link HERE (REGEX101) 将向您展示一个示例,如果您愿意,您可以在其中使用正则表达式。
我在上面提到的 sub-string 比 .com
具有更大的方差。
例如,您可以使用 (\s*)(?=\.\w{3,})
。
此正则表达式的问题在于,即使它匹配 .txt
、.org
、.json
和 .unclepetespurplebeet
,正则表达式也不安全。当使用问题的字符串...
"as.asd.sd fdsfs. dfsd d.sdfsd. sdfsdf sd .COM"
例如,您可以在 LINK HERE (Regex101) 处看到字符串中有 3 行。这些线表示 sub-string 的前瞻断言返回 true 的区域。每次断言为真时,都会产生不正确的最终匹配的可能性。虽然最后只返回了一个匹配项,而且是正确的匹配项,但在程序或网站中实现时,在生产中是 运行,你几乎可以保证正则表达式不仅会失败,而且会失败得可怕,你会开始讨厌它。
我的字符串形式为:
"as.asd.sd fdsfs. dfsd d.sdfsd. sdfsdf sd .COM"
我只想匹配最后一个句号(.)之前的最后一段空白
到目前为止,我能够捕获空格,但不能捕获 very 最后一次使用:
\s+(?=\.\w)
如何让它不那么贪心?
在一般情况下,您可以使用以下方案匹配最后一次出现的任何模式:
pattern(?![\s\S]*pattern)
(?s)pattern(?!.*pattern)
pattern(?!(?s:.*)pattern)
其中 [\s\S]*
尽可能多地匹配任意零个或多个字符。 (?s)
和 (?s:.)
可以与支持这些结构的正则表达式引擎一起使用,以便使用 .
匹配任何字符。
在这种情况下,而不是\s+(?![\s\S]*\s)
,您可以使用
\s+(?!\S*\s)
见regex demo。注意 \s
和 \S
是相反的 类,因此,这里使用 [\s\S]*
是没有意义的, \S*
就足够了。
详情:
\s+
- 一个或多个空白字符(?!\S*\s)
- 后面没有紧跟任何 0 个或更多 non-whitespace 个字符,然后是一个空格。
你可以这样试试:
(\s+)(?=\.[^.]+$)
(?=\.[^.]+$)
正向预测一个点和除行尾点以外的字符。
演示:
你可以试试这个。它将捕获第一个捕获组中的最后一个白色 space 段。
(\s+)\.[^\.]*$
"as.asd.sd ffindMyLastOccurrencedsfs. dfindMyLastOccurrencefsd d.sdfsd. sdfsdf sd ..COM"
.*(?=((?<=\S)\s+)).*
replaced by `><`
> <
作为一个更普遍的例子
此示例定义了多个针并查找其中任何一个的最后一次出现。在这个例子中,针是:
- 定义词
findMyLastOccurrence
- 空格
(?<=\S)\s+
- 点
(?<=[^\.])\.+
"as.asd.sd ffindMyLastOccurrencedsfs. dfindMyLastOccurrencefsd d.sdfsd. sdfsdf sd ..COM"
.*(?=(findMyLastOccurrence|(?<=\S)\s+|(?<=[^\.])\.+)).*
replaced by `><`
>..<
解释:
第 1 部分 .*
- 贪心,只要找到针头什么都找。因此,它还会捕获所有出现的针,直到最后一根针。
编辑添加:
- 如果我们对第一个命中感兴趣,我们可以通过编写
.*?
来防止贪婪
第 2 部分 (?=(findMyLastOccurrence|(?<=\S)\s+|(?<=[^\.])\.+|(?<=**Not**NeedlePart)NeedlePart+))
- 定义贪心'find-all'的'break'条件。它由几个部分组成:
(?=(needles))
- positive lookahead:确保之前找到的everything之后是针
findMyLastOccurrence|(?<=\S)\s+|(?<=[^\.])\.+)|(?<=**Not**NeedlePart)NeedlePart+
- 我们正在寻找的几根针。针本身就是图案。
- 如果我们寻找一组空白、点或其他针刺部分,我们正在寻找的图案实际上是:任何 不是 一个针部分,后跟一个或多个针部分(因此针部分为+)。请参阅用 \S, actual dot 否定空格 \s 的示例。用 [^.] 否定
- positive lookahead:确保之前找到的everything之后是针
第 3 部分 .*
- 因为我们对其余部分不感兴趣,所以我们捕获它并且不再使用它。我们可以用括号捕获它并将其用作另一个组,但这超出了这里的范围
常见问题的简单解决方案
我通读的所有答案都偏离主题、过于复杂或根本不正确。这个问题是一个常见的问题,正则表达式提供了一个简单的解决方案。
分解一般问题
字符串
- 普遍的问题是有一个 string 包含几个字符。
SUB-STRING
- 在字符串中是由几个字符组成的sub-string。通常这是文件扩展名(即
.c
、.ts
或.json
)或顶级域(即.com
、.org
或.io
),但它可以像MC Donald's Mulan Szechuan Sauce
一样随意。关键是,它可能并不总是那么简单。
- 在字符串中是由几个字符组成的sub-string。通常这是文件扩展名(即
方差之前(最重要的部分)
- before variance 是一个或多个任意字符,总是出现在 sub-string 之前。在这道题中,之前的方差是一个未知数white-space。这是一个差异,因为需要匹配的 white-space 的数量会变化(或具有动态数量)。
参考问题描述解决方案
(解决方案第 1 部分)
通常在使用正则表达式时需要反向工作。
我们将从上述问题的末尾开始,往后做;我们将从 The Before Variance(或 #3)
开始所以,如上所述,之前的方差是white-space的未知数。我们知道它包括 white-space,但我们不知道有多少,所以我们将使用 元序列用于 Any Whitespce 和 一个或多个量词.
“任何空白”的元序列是
\s
。“一个或多个”量词是
+
所以我们将从...开始...
注意:在 ECMAS Regex 中,/
字符就像字符串周围的引号。
const regex = /\s+/g
我还包含了 g
来告诉引擎将全局标志设置为 true。为了简洁起见,我不会解释标志,但是如果你不知道全局标志的作用,你应该去DuckDuckGo。
(解决方案第 2 部分)
请记住,我们正在反向工作,因此下一个要关注的部分是 Sub-string。在这个问题中它是.com
,但作者可能希望它匹配一个具有方差的值,而不仅仅是静态字符串.com
,因此我将在下面详细讨论,但是保持专注,我们现在将与 .com
合作。
我们有必要在这里使用一个概念,叫做零长度断言。我们需要一个“zero-length 断言”,因为我们有一个重要的 sub-string,但不是我们想要匹配的。 “Zero-length 断言”允许我们移动正则表达式引擎正在查看的字符串中的点,而无需匹配任何字符即可到达那里。
我们要用到的Zero-Length断言叫做LOOK AHEAD,语法如下。
Look-ahead 语法:(?=Your-SubStr-Here)
我们将使用前瞻性来匹配分配给 look-ahead 的模式之前出现的方差,这将是我们的 sub-string。结果如下所示:
const regex = /\s+(?=\.com)/gi
我添加了 insensitive 标志来告诉引擎不关心字母的大小写,换句话说;正则表达式 /\s+(?=\.cOM)/gi
与 /\s+(?=\.Com)/gi
相同,两者都与:/\s+(?=\.com)/gi
&/or /\s+(?=.COM)/gi 相同。只要设置了 i
标志,“刚刚列出”的每个正则表达式都是等效的。
就是这样! The link HERE (REGEX101) 将向您展示一个示例,如果您愿意,您可以在其中使用正则表达式。
我在上面提到的 sub-string 比 .com
具有更大的方差。
例如,您可以使用 (\s*)(?=\.\w{3,})
。
此正则表达式的问题在于,即使它匹配 .txt
、.org
、.json
和 .unclepetespurplebeet
,正则表达式也不安全。当使用问题的字符串...
"as.asd.sd fdsfs. dfsd d.sdfsd. sdfsdf sd .COM"
例如,您可以在 LINK HERE (Regex101) 处看到字符串中有 3 行。这些线表示 sub-string 的前瞻断言返回 true 的区域。每次断言为真时,都会产生不正确的最终匹配的可能性。虽然最后只返回了一个匹配项,而且是正确的匹配项,但在程序或网站中实现时,在生产中是 运行,你几乎可以保证正则表达式不仅会失败,而且会失败得可怕,你会开始讨厌它。