关于正则表达式:如何在正则表达式中匹配“直到这个字符序列”的任何内容?

How to match “anything up until this sequence of characters” in a regular expression?

取这个正则表达式:/^[^abc]/。这将匹配字符串开头的任何单个字符,除了a、b或c。

如果在后面添加*/^[^abc]*/–正则表达式将继续向结果中添加每个后续字符,直到它遇到a–或b–或c–为止。

例如,对于源字符串"qwerty qwerty whatever abc hello",表达式将与"qwerty qwerty wh"匹配。

但是如果我想要匹配的字符串是"qwerty qwerty whatever",怎么办?

…换句话说,我怎样才能匹配(但不包括)精确序列"abc"


您没有指定要使用的regex的口味,但这将在任何一个最受欢迎的,可以被认为是"完整的"。

1
/.+?(?=abc)/

它是如何工作的

.+?部分是.+的非贪婪版本(一个或多个什么都行。当我们使用.+时,发动机基本上可以匹配所有部件。然后,如果regex中还有其他内容,它将逐步返回正在尝试匹配以下部分。这是贪婪的行为,尽可能满足的意思。

当使用.+?时,不要一次匹配全部,而是返回其他条件(如果有),引擎将按匹配下一个字符步骤,直到regex的后续部分匹配为止(如果有则再次匹配)。这是不贪婪的,意思是尽可能少的匹配满足。

1
2
3
4
5
/.+X/  ~"abcXabcXabcX"        /.+/  ~"abcXabcXabcX"
          ^^^^^^^^^^^^                  ^^^^^^^^^^^^

/.+?X/ ~"abcXabcXabcX"        /.+?/ ~"abcXabcXabcX"
          ^^^^                          ^

接下来我们有了(?={contents}),一个零宽度断言,环顾四周。此分组结构与内容,但不算作匹配的字符(零宽度)。它只有匹配或不匹配时才返回(断言)。

因此,在其他术语中,regex /.+?(?=abc)/表示:

Match any characters as few as possible until a "abc" is found,
without counting the"abc".


如果你想捕捉到"ABC"之前的一切:

1
/^(.*?)abc/

说明:

( )捕获括号内的表达式,以便使用$1$2等进行访问。

^匹配行首

.*匹配任何内容,?不贪婪地(匹配所需的最小字符数)-[1]

[1]之所以需要这样做,是因为在以下字符串中:

1
whatever whatever something abc something abc

默认情况下,正则表达式是贪婪的,这意味着它将尽可能匹配。因此,/^.*abc/将匹配"任何ABC某物"。添加非贪婪量词?,使得regex只匹配"随便什么"。


正如@jared ng和@issun指出的,解决此类regex的关键是"将所有内容匹配到某个单词或子字符串"或"在某个单词或子字符串之后匹配所有内容",这称为"lookaround"零长度断言。在这里阅读更多关于它们的信息。

在您的特定情况下,可以通过积极的展望来解决。一幅画胜过千言万语。请参见屏幕截图中的详细说明。

Regex101 Screenshot


你需要的是看看像.+? (?=abc)这样的断言。

参见:lookahead和lookbehind零长度断言

注意,[abc]abc不同。括号内不是字符串-每个字符只是一种可能性。在括号外,它变成了字符串。


这对于regex是有意义的。

  • 确切的单词可以从以下regex命令中获得:
  • ("(.*?)")/g

    在这里,我们可以从全局中得到双引号内的确切单词。例如,如果我们的搜索文本是,

    这是"双引号"单词的示例

    然后我们将从那个句子中得到"双引号"。


    对于Java中的正则表达式,我相信在大多数正则表达式引擎中,如果要包含最后一部分,这将是可行的:

    1
    .+?(abc)

    例如,在此行中:

    1
    I have this very nice senabctence

    选择"abc"之前的所有字符,还包括abc

    使用我们的regex,结果将是:I have this very nice senabc

    测试:https://regex101.com/r/mx51ru/1


    在寻求帮助解决我的问题后,我结束了这个stackoverflow问题,但没有找到解决方法:(

    所以我必须即兴发挥…过了一段时间,我终于找到了我需要的雷杰克斯:

    enter image description here

    如您所见,我需要在"GRP BPS"文件夹之前最多有一个文件夹,而不包括最后一个破折号。并且在"grp bps"文件夹之后至少要有一个文件夹。


    我相信你需要子表达式。如果我记得对的话,你可以用普通的()括号来表示子表达式。

    本部分来自GREP手册:

    1
    2
    3
    4
    5
     Back References and Subexpressions
           The back-reference
    , where n is a single digit, matches the substring
           previously matched  by  the  nth  parenthesized  subexpression  of  the
           regular expression.

    做一些像^[^(abc)]应该做的事情。


    $标志着一个字符串的结束,所以类似这样的东西应该是有效的:[[^abc]*]$在这里你要寻找的任何东西都不是在abc的任何迭代中结束的,但是它必须在结束时

    另外,如果您在regex中使用脚本语言(如php或js),它们有一个搜索函数,当它第一次遇到模式时停止(您可以指定从左开始或从右开始,或者使用php,您可以执行内爆来镜像字符串)。


    试试这个

    1
    .+?efg

    查询:

    1
    select REGEXP_REPLACE ('abcdefghijklmn','.+?efg', '') FROM dual;

    输出:

    1
    hijklmn