How to match “anything up until this sequence of c

2019-01-01 09:33发布

Take this regular expression: /^[^abc]/. This will match any single character at the beginning of a string, except a, b, or c.

If you add a * after it – /^[^abc]*/ – the regular expression will continue to add each subsequent character to the result, until it meets either an a, or b, or c.

For example, with the source string "qwerty qwerty whatever abc hello", the expression will match up to "qwerty qwerty wh".

But what if I wanted the matching string to be "qwerty qwerty whatever "

...In other words, how can I match everything up to (but not including) the exact sequence "abc"?

标签: regex
10条回答
笑指拈花
2楼-- · 2019-01-01 10:25

If you're looking to capture everything up to "abc":

/^(.*?)abc/

Explanation:

( ) capture the expression inside the parentheses for access using $1, $2, etc.

^ match start of line

.* match anything, ? non-greedily (match the minimum number of characters required) - [1]

[1] The reason why this is needed is that otherwise, in the following string:

whatever whatever something abc something abc

by default, regexes are greedy, meaning it will match as much as possible. Therefore /^.*abc/ would match "whatever whatever something abc something ". Adding the non-greedy quantifier ? makes the regex only match "whatever whatever something ".

查看更多
回忆,回不去的记忆
3楼-- · 2019-01-01 10:25

What you need is look around assertion like .+? (?=abc).

See: Lookahead and Lookbehind Zero-Length Assertions

Be aware that [abc] isn't the same as abc. Inside brackets it's not a string - each character is just one of the possibilities. Outside the brackets it becomes the string.

查看更多
泪湿衣
4楼-- · 2019-01-01 10:27

You didn't specify which flavor of regex you're using, but this will work in any of the most popular ones that can be considered "complete".

/.+?(?=abc)/

How it works

The .+? part is the un-greedy version of .+ (one or more of anything). When we use .+, the engine will basically match everything. Then, if there is something else in the regex it will go back in steps trying to match the following part. This is the greedy behavior, meaning as much as possible to satisfy.

When using .+?, instead of matching all at once and going back for other conditions (if any), the engine will match the next characters by step until the subsequent part of the regex is matched (again if any). This is the un-greedy, meaning match the fewest possible to satisfy.

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

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

Following that we have (?={contents}), a zero width assertion, a look around. This grouped construction matches its contents, but does not count as characters matched (zero width). It only returns if it is a match or not (assertion).

Thus, in other terms the regex /.+?(?=abc)/ means:

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

查看更多
何处买醉
5楼-- · 2019-01-01 10:30

For regex in Java, and I believe also in most regex engines, if you want to include the last part this will work:

.+?(abc)

For example, in this line:

I have this very nice senabctence

select all characters until "abc" and also include abc

using our regex, the result will be: I have this very nice senabc

Test this out: https://regex101.com/r/mX51ru/1

查看更多
登录 后发表回答