正则表达式中的非捕获组是什么?

发布于 2024-09-15 06:34:52 字数 52 浏览 4 评论 0原文

非捕获组(即 (?:))如何在正则表达式中使用?它们有什么用处?

How are non-capturing groups, i.e., (?:), used in regular expressions and what are they good for?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

半葬歌 2024-09-22 06:34:52

让我尝试用一​​个例子来解释这一点。

考虑以下文本:

http://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex

现在,如果我将下面的正则表达式应用于它(为了清楚起见,我没有转义斜杠;使用它时,斜杠必须转义为 \/

(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?      // slashes not escaped for clarity
(https?|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?   // slashes escaped

...。 .. 我会得到以下结果:

Match "http://stackoverflow.com/"
     Group 1: "http"
     Group 2: "stackoverflow.com"
     Group 3: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "https"
     Group 2: "stackoverflow.com"
     Group 3: "/questions/tagged/regex"

但我不关心协议——我只想要 URL 的主机和路径。因此,我更改了正则表达式以包含非捕获组 (?:)

(?:https?|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?   // slashes escaped

现在,我的结果如下所示:

Match "http://stackoverflow.com/"
     Group 1: "stackoverflow.com"
     Group 2: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "stackoverflow.com"
     Group 2: "/questions/tagged/regex"

看到了吗?第一组尚未被俘获。解析器使用它来匹配文本,但稍后在最终结果中忽略它。


编辑:

根据要求,让我也尝试解释一下组。

嗯,团体有很多用途。它们可以帮助您从更大的匹配(也可以命名)中提取准确的信息,它们可以让您重新匹配以前的匹配组,并且可以用于替换。让我们尝试一些例子,好吗?

假设您有某种 XML 或 HTML(请注意 正则表达式可能不是完成这项工作的最佳工具,但作为一个例子很不错)。您想要解析标签,所以您可以执行类似的操作(我添加了空格以使其更易于理解):

   \<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\>
or
   \<(.+?)\> [^<]*? \</\1\>

第一个正则表达式有一个命名组(TAG),而第二个正则表达式使用一个公共组。两个正则表达式都执行相同的操作:它们使用第一组中的值(标记的名称)来匹配结束标记。区别在于第一个使用名称来匹配值,第二个使用组索引(从 1 开始)。

现在让我们尝试一些替代品。考虑以下文本:

Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.

现在,让我们在其上使用这个愚蠢的正则表达式:

\b(\S)(\S)(\S)(\S*)\b

此正则表达式匹配至少包含 3 个字符的单词,并使用组来分隔前三个字母。结果是这样的:

Match "Lorem"
     Group 1: "L"
     Group 2: "o"
     Group 3: "r"
     Group 4: "em"
Match "ipsum"
     Group 1: "i"
     Group 2: "p"
     Group 3: "s"
     Group 4: "um"
...

Match "consectetuer"
     Group 1: "c"
     Group 2: "o"
     Group 3: "n"
     Group 4: "sectetuer"
...

因此,如果我们在其上应用替换字符串:

$1_$3$2_$4

...,我们将尝试使用第一组,添加下划线,使用第三组,然后使用第二组,添加另一个下划线,然后第四组。结果字符串如下所示。

L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.

您也可以使用命名组进行替换,使用 ${name}

要使用正则表达式,我建议 http://regex101.com/,它提供了大量有关如何使用的详细信息正则表达式有效;它还提供了一些正则表达式引擎可供选择。

Let me try to explain this with an example.

Consider the following text:

http://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex

Now, if I apply the regex below over it (I did not escape the slashes for clarity; when using it, slashes would have to be escaped to \/ )...

(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)?      // slashes not escaped for clarity
(https?|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?   // slashes escaped

... I would get the following result:

Match "http://stackoverflow.com/"
     Group 1: "http"
     Group 2: "stackoverflow.com"
     Group 3: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "https"
     Group 2: "stackoverflow.com"
     Group 3: "/questions/tagged/regex"

But I don't care about the protocol -- I just want the host and path of the URL. So, I change the regex to include the non-capturing group (?:).

(?:https?|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)?   // slashes escaped

Now, my result looks like this:

Match "http://stackoverflow.com/"
     Group 1: "stackoverflow.com"
     Group 2: "/"

Match "https://stackoverflow.com/questions/tagged/regex"
     Group 1: "stackoverflow.com"
     Group 2: "/questions/tagged/regex"

See? The first group has not been captured. The parser uses it to match the text, but ignores it later, in the final result.


EDIT:

As requested, let me try to explain groups too.

Well, groups serve many purposes. They can help you to extract exact information from a bigger match (which can also be named), they let you rematch a previous matched group, and can be used for substitutions. Let's try some examples, shall we?

Imagine you have some kind of XML or HTML (be aware that regex may not be the best tool for the job, but it is nice as an example). You want to parse the tags, so you could do something like this (I have added spaces to make it easier to understand):

   \<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\>
or
   \<(.+?)\> [^<]*? \</\1\>

The first regex has a named group (TAG), while the second one uses a common group. Both regexes do the same thing: they use the value from the first group (the name of the tag) to match the closing tag. The difference is that the first one uses the name to match the value, and the second one uses the group index (which starts at 1).

Let's try some substitutions now. Consider the following text:

Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.

Now, let's use this dumb regex over it:

\b(\S)(\S)(\S)(\S*)\b

This regex matches words with at least 3 characters, and uses groups to separate the first three letters. The result is this:

Match "Lorem"
     Group 1: "L"
     Group 2: "o"
     Group 3: "r"
     Group 4: "em"
Match "ipsum"
     Group 1: "i"
     Group 2: "p"
     Group 3: "s"
     Group 4: "um"
...

Match "consectetuer"
     Group 1: "c"
     Group 2: "o"
     Group 3: "n"
     Group 4: "sectetuer"
...

So, if we apply the substitution string:

$1_$3$2_$4

... over it, we are trying to use the first group, add an underscore, use the third group, then the second group, add another underscore, and then the fourth group. The resulting string would be like the one below.

L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.

You can use named groups for substitutions too, using ${name}.

To play around with regexes, I recommend http://regex101.com/, which offers a good amount of details on how the regex works; it also offers a few regex engines to choose from.

傲世九天 2024-09-22 06:34:52

您可以使用捕获组来组织和解析表达式。非捕获组具有第一个好处,但没有第二个好处。例如,您仍然可以说非捕获组是可选的。

假设您想匹配数字文本,但某些数字可以写为 1st、2nd、3rd、4th... 如果您想捕获数字部分,但不捕获(可选)后缀,您可以使用非捕获组。

([0-9]+)(?:st|nd|rd|th)?

这将匹配 1, 2, 3... 形式的数字或 1st, 2nd, 3rd... 形式的数字,但它只会捕获数字部分。

You can use capturing groups to organize and parse an expression. A non-capturing group has the first benefit, but doesn't have the overhead of the second. You can still say a non-capturing group is optional, for example.

Say you want to match numeric text, but some numbers could be written as 1st, 2nd, 3rd, 4th,... If you want to capture the numeric part, but not the (optional) suffix you can use a non-capturing group.

([0-9]+)(?:st|nd|rd|th)?

That will match numbers in the form 1, 2, 3... or in the form 1st, 2nd, 3rd,... but it will only capture the numeric part.

情泪▽动烟 2024-09-22 06:34:52

?: 用于当您想要对表达式进行分组,但又不想将其保存为字符串的匹配/捕获部分时。

一个例子是匹配 IP 地址的内容:

/(?:\d{1,3}\.){3}\d{1,3}/

请注意,我不关心保存前 3 个八位字节,但是 (?:...) 分组允许我缩短正则表达式而不会产生捕获和存储匹配的开销。

?: is used when you want to group an expression, but you do not want to save it as a matched/captured portion of the string.

An example would be something to match an IP address:

/(?:\d{1,3}\.){3}\d{1,3}/

Note that I don't care about saving the first 3 octets, but the (?:...) grouping allows me to shorten the regex without incurring the overhead of capturing and storing a match.

玩物 2024-09-22 06:34:52

历史动机:

非捕获组的存在可以用括号来解释。

考虑表达式 (a|b)ca|bc,由于连接优先于 |,这些表达式代表两种不同的语言 (分别为 {ac, bc}{a, bc})。

但是,括号也用作匹配组(如其他答案所解释的......)。

当您想要有括号但不捕获子表达式时,请使用非捕获组。在示例中,(?:a|b)c

HISTORICAL MOTIVATION:

The existence of non-capturing groups can be explained with the use of parenthesis.

Consider the expressions (a|b)c and a|bc, due to priority of concatenation over |, these expressions represent two different languages ({ac, bc} and {a, bc} respectively).

However, the parenthesis are also used as a matching group (as explained by the other answers...).

When you want to have parenthesis but not capture the sub-expression you use NON-CAPTURING GROUPS. In the example, (?:a|b)c

只想待在家 2024-09-22 06:34:52

让我尝试一下这个例子:

正则表达式代码:(?:animal)(?:=)(\w+)(,)\1\2

搜索字符串:

第 1 行 - animal=cat,dog,cat,tiger,dog

第 2 行 - animal=cat,cat,dog,dog,tiger

第 3 行- animal=dog,dog,cat,cat,tiger

(?:animal) -->非捕获组 1

(?:=)-->非捕获组 2

(\w+)-->捕获组 1

(,)-->捕获组 2

\1 -->捕获组 1 的结果,即第 1 行是猫,第 2 行是猫,第 3 行是狗。

\2 -->捕获组 2 的结果,即逗号 (,)

因此,在此代码中,通过给出 \1\2 我们稍后分别调用或重复捕获组 1 和 2 的结果代码。

根据代码的顺序 (?:animal) 应该是第 1 组,(?:=) 应该是第 2 组并继续..

但是通过给出 ?: 我们将匹配组设置为非捕获组(在匹配组中不进行计数,因此分组编号从第一个捕获组开始,而不是从非捕获组开始),以便重复匹配结果-group (?:animal) 稍后无法在代码中调用。

希望这能解释非捕获组的使用。

在此处输入图像描述

Let me try this with an example:

Regex Code: (?:animal)(?:=)(\w+)(,)\1\2

Search String:

Line 1 - animal=cat,dog,cat,tiger,dog

Line 2 - animal=cat,cat,dog,dog,tiger

Line 3 - animal=dog,dog,cat,cat,tiger

(?:animal) --> Non-Captured Group 1

(?:=)--> Non-Captured Group 2

(\w+)--> Captured Group 1

(,)--> Captured Group 2

\1 --> result of captured group 1 i.e In Line 1 is cat, In Line 2 is cat, In Line 3 is dog.

\2 --> result of captured group 2 i.e comma (,)

So in this code by giving \1 and \2 we recall or repeat the result of captured group 1 and 2 respectively later in the code.

As per the order of code (?:animal) should be group 1 and (?:=) should be group 2 and continues..

but by giving the ?: we make the match-group non captured (which do not count off in matched group, so the grouping number starts from the first captured group and not the non captured), so that the repetition of the result of match-group (?:animal) can't be called later in code.

Hope this explains the use of non capturing group.

enter image description here

鸠书 2024-09-22 06:34:52

它使该组成为非捕获,这意味着该组匹配的子字符串将不会包含在捕获列表中。 Ruby 中的一个例子来说明差异:

"abc".match(/(.)(.)./).captures #=> ["a","b"]
"abc".match(/(?:.)(.)./).captures #=> ["b"]

It makes the group non-capturing, which means that the substring matched by that group will not be included in the list of captures. An example in ruby to illustrate the difference:

"abc".match(/(.)(.)./).captures #=> ["a","b"]
"abc".match(/(?:.)(.)./).captures #=> ["b"]
梦亿 2024-09-22 06:34:52

您稍后可以在正则表达式中使用捕获的组来匹配或者您可以在正则表达式的替换部分中使用它们。创建一个非捕获组只会使该组免于因上述任一原因而被使用。

如果您尝试捕获许多不同的事物并且有一些您不想捕获的组,则非捕获组非常有用。

这几乎就是它们存在的原因。当您学习组时,请了解原子组,它们的作用很多!还有环视组,但它们稍微复杂一些,并且使用得不多。

稍后在正则表达式中使用的示例(反向引用):

<([AZ][A-Z0-9]*)\b[^>]*>.*?< /code> [ Finds an x​​ml tag (without ns support) ]

([AZ][A-Z0-9]*) 是一个捕获组(在本例中是标记名)

稍后在正则表达式为 \1 这意味着它只会匹配第一组中的相同文本(([AZ][A-Z0-9]*) 组)(在本例中它与结束标记匹配)。

Groups that capture you can use later on in the regex to match OR you can use them in the replacement part of the regex. Making a non-capturing group simply exempts that group from being used for either of these reasons.

Non-capturing groups are great if you are trying to capture many different things and there are some groups you don't want to capture.

Thats pretty much the reason they exist. While you are learning about groups, learn about Atomic Groups, they do a lot! There is also lookaround groups but they are a little more complex and not used so much.

Example of using later on in the regex (backreference):

<([A-Z][A-Z0-9]*)\b[^>]*>.*?</\1> [ Finds an xml tag (without ns support) ]

([A-Z][A-Z0-9]*) is a capturing group (in this case it is the tagname)

Later on in the regex is \1 which means it will only match the same text that was in the first group (the ([A-Z][A-Z0-9]*) group) (in this case it is matching the end tag).

待天淡蓝洁白时 2024-09-22 06:34:52

简单的答案

使用它们来确保此处出现几种可能性之一 (?:one|two) 或可选短语 camp(?:site)? 或一般情况下的任何地方您想要建立一个组/短语/部分而不需要专门引用它。

他们将您捕获的群体数量降至最低。

A Simple Answer

Use them to ensure one of several possibilities occur here (?:one|two) or an optional phrase camp(?:site)? or in general, anywhere you want to establish a group/phrase/section without needing to refer to it specifically.

They keep your captured group(s) count to a minimum.

此生挚爱伱 2024-09-22 06:34:52

tl;dr 非捕获组,顾名思义,是您不希望包含在捕获中的正则表达式部分,而 ?: 是一种方法将一个组定义为非捕获组。

假设您有一个电子邮件地址[电子邮件受保护].以下正则表达式将创建两个,即 id 部分和 @example.com 部分。 (\p{Alpha}*[az])(@example.com)。为了简单起见,我们提取整个域名,包括 @ 字符。

现在假设您只需要地址的 id 部分。你想要做的是抓取匹配结果的第一组,在正则表达式中用 () 包围,实现这一点的方法是使用非捕获组语法,即 ?:。因此,正则表达式 (\p{Alpha}*[az])(?:@example.com) 将仅返回电子邮件的 id 部分。

tl;dr non-capturing groups, as the name suggests are the parts of the regex that you do not want to be included in the capture and ?: is a way to define a group as being non-capturing.

Let's say you have an email address [email protected]. The following regex will create two groups, the id part and @example.com part. (\p{Alpha}*[a-z])(@example.com). For simplicity's sake, we are extracting the whole domain name including the @ character.

Now let's say, you only need the id part of the address. What you want to do is to grab the first group of the match result, surrounded by () in the regex and the way to do this is to use the non-capturing group syntax, i.e. ?:. So the regex (\p{Alpha}*[a-z])(?:@example.com) will return just the id part of the email.

坦然微笑 2024-09-22 06:34:52

我无法对最重要的答案发表评论:我想添加一个仅在最重要的答案中隐含的明确观点:

非捕获组 (?:...) 确实 不删除原始完全匹配中的任何字符,它只是以可视方式重新组织正则表达式给程序员。

要访问正则表达式的特定部分而不定义无关字符,您始终需要使用 .group()

I cannot comment on the top answers to say this: I would like to add an explicit point which is only implied in the top answers:

The non-capturing group (?:...) does not remove any characters from the original full match, it only reorganises the regex visually to the programmer.

To access a specific part of the regex without defined extraneous characters you would always need to use .group(<index>)

悲喜皆因你 2024-09-22 06:34:52

为了补充本线程中的其他好的答案,我想添加我遇到的一个有趣的观察。

发现:您可以在非捕获组内添加捕获组。

问题详细信息:看看下面的正则表达式来匹配网页网址:

var parse_url_regex = /^(?:([A-Za-z]+):)(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

这是我的输入网址字符串:

var url = "http://www.ora.com:80/goodparts?q#fragment";

我的正则表达式中的第一组 (?:([A-Za-z]+) :) 是一个非捕获组,它与协议方案 (http) 和冒号 (:) 字符匹配。接下来它变成http:。但是当我运行下面的代码时:

console.debug(parse_url_regex.exec(url));

我可以看到返回数组的第一个st索引包含字符串http(请参阅屏幕截图)。

输入图像描述这里

此时,我的想法是 http 和冒号 : 都不会在输出中报告,因为它们位于非捕获组内。如果第一个正则表达式组 (?:([A-Za-z]+):) 是非捕获组,那么为什么它在输出中返回 http 字符串大批?

说明:如果您注意到,([A-Za-z]+) 是一个捕获组(开头没有 ?: )。但此捕获组本身位于非捕获组 (?:([A-Za-z]+):) 内,后跟 : 字符。这就是为什么文本 http 仍然被捕获,但落入非捕获组内(但在捕获组外)的冒号 : 字符不会在输出数组。

To complement other good answers in this thread, I want to add an interesting observation that I came across.

Finding: You can have a capturing group inside a non-capturing group.

Problem Details: Have a look at below regex for matching web urls:

var parse_url_regex = /^(?:([A-Za-z]+):)(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

Here is my input url string:

var url = "http://www.ora.com:80/goodparts?q#fragment";

The first group in my regex (?:([A-Za-z]+):) is a non-capturing group which matches the protocol scheme (http) and colon (:) character. In continuation it becomes http:. But when I ran below code:

console.debug(parse_url_regex.exec(url));

I could see that the 1st index of the returned array was containing the string http instead (Refer screenshot).

enter image description here

At this point, my thinking was that http and colon : both will not get reported in the output as they are inside a non-capturing group. If the first regex group (?:([A-Za-z]+):) is a non-capturing group then why it is returning http string in the output array?

Explanation: So if you notice, ([A-Za-z]+) is a capturing group (not having ?: at the beginning). But this capturing group is itself inside a non-capturing group (?:([A-Za-z]+):) followed by a : character. That's why the text http still gets captured but the colon : character which is falling inside the non-capturing group (but outside the capturing group ) doesn't get reported in the output array.

北恋 2024-09-22 06:34:52

我是一名 JavaScript 开发人员,我将尝试解释它对于 JavaScript 的重要性。

考虑一个场景,您想要匹配 cat is Animal
当你想要匹配猫和动物时,两者之间应该有一个 is

 // this will ignore "is" as that's is what we want
"cat is animal".match(/(cat)(?: is )(animal)/) ;
result ["cat is animal", "cat", "animal"]

 // using lookahead pattern it will match only "cat" we can
 // use lookahead but the problem is we can not give anything
 // at the back of lookahead pattern
"cat is animal".match(/cat(?= is animal)/) ;
result ["cat"]

 //so I gave another grouping parenthesis for animal
 // in lookahead pattern to match animal as well
"cat is animal".match(/(cat)(?= is (animal))/) ;
result ["cat", "cat", "animal"]

 // we got extra cat in above example so removing another grouping
"cat is animal".match(/cat(?= is (animal))/) ;
result ["cat", "animal"]

Well I am a JavaScript developer and will try to explain its significance pertaining to JavaScript.

Consider a scenario where you want to match cat is animal
when you would like match cat and animal and both should have a is in between them.

 // this will ignore "is" as that's is what we want
"cat is animal".match(/(cat)(?: is )(animal)/) ;
result ["cat is animal", "cat", "animal"]

 // using lookahead pattern it will match only "cat" we can
 // use lookahead but the problem is we can not give anything
 // at the back of lookahead pattern
"cat is animal".match(/cat(?= is animal)/) ;
result ["cat"]

 //so I gave another grouping parenthesis for animal
 // in lookahead pattern to match animal as well
"cat is animal".match(/(cat)(?= is (animal))/) ;
result ["cat", "cat", "animal"]

 // we got extra cat in above example so removing another grouping
"cat is animal".match(/cat(?= is (animal))/) ;
result ["cat", "animal"]
季末如歌 2024-09-22 06:34:52

在复杂的正则表达式中,您可能会遇到这样的情况:您希望使用大量组,其中一些组用于重复匹配,另一些组用于提供反向引用。默认情况下,匹配每个组的文本被加载到反向引用数组中。如果我们有很多组,并且只需要能够从反向引用数组中引用其中一些组,我们可以覆盖此默认行为,以告诉正则表达式某些组仅用于重复处理,不需要捕获和存储在反向引用数组中。

In complex regular expressions you may have the situation arise where you wish to use a large number of groups some of which are there for repetition matching and some of which are there to provide back references. By default the text matching each group is loaded into the backreference array. Where we have lots of groups and only need to be able to reference some of them from the backreference array we can override this default behaviour to tell the regular expression that certain groups are there only for repetition handling and do not need to be captured and stored in the backreference array.

猫九 2024-09-22 06:34:52

让我给你举一个地理坐标的例子,下面匹配两个组

Latitude,Longitude

([+-]?\d+(?:\.\d+)?),([+-]?\d+(?:\.\d+)?)

让我们取一个 ([+-]?\d+(?:\.\d+)?)

坐标可以是整数,例如 58 也可以是 58.666
因此,提到了可选的 (.666) 第二部分 (\.\d+)?

(...)? - for optional

但括号里的是,那将是另一组比赛。我们不需要两个匹配,一个匹配 58,另一个匹配 .666,我们需要单个纬度作为匹配。这里是非捕获组 (?:)

和非捕获组 [+-]?\d+(?:\.\d+)?, 58.666和58都是单场比赛

Let me take to you an example of geo coordinate, the below matches two groups

Latitude,Longitude

([+-]?\d+(?:\.\d+)?),([+-]?\d+(?:\.\d+)?)

Lets take one ([+-]?\d+(?:\.\d+)?)

co-ordinate can be whole number like 58 or could be 58.666

Hence the optional (.666) second part (\.\d+)? is mentioned.

(...)? - for optional

But it is parenthesised, that will be another group of match. and we dont want two matches one for 58 and another for .666, we need single latitude as match. Here comes non-capturing group (?:)

with non-capturing group [+-]?\d+(?:\.\d+)?, 58.666 and 58 both are single match

满身野味 2024-09-22 06:34:52

(?: ... ) 作为一个组 ( ... ) 但不捕获匹配的数据。它确实比标准捕获组高效得多。当您想要对某些内容进行分组但稍后不需要重复使用时可以使用它。 @托托

(?: ... ) acts as a group ( ... ) but doesn't capture the matched data. It's really much more efficient than a standard capture group. It is use when you want to group something but don't need to reuse it later. @Toto

梦过后 2024-09-22 06:34:52

它非常简单,我们可以通过简单的日期示例来理解,假设如果提到日期为2019年1月1日或2019年5月2日或任何其他日期,我们只想将其转换为dd/mm/yyyy格式我们不需要月份的名称(一月或二月),因此为了捕获数字部分,而不是(可选)后缀,您可以使用非捕获组。

所以正则表达式就是,

([0-9]+)(?:January|February)?

就这么简单。

Its extremely simple, We can understand with simple date example, suppose if the date is mentioned as 1st January 2019 or 2nd May 2019 or any other date and we simply want to convert it to dd/mm/yyyy format we would not need the month's name which is January or February for that matter, so in order to capture the numeric part, but not the (optional) suffix you can use a non-capturing group.

so the regular expression would be,

([0-9]+)(?:January|February)?

Its as simple as that.

风月客 2024-09-22 06:34:52

我想我会给你答案。在未检查匹配是否成功的情况下,请勿使用捕获变量。

除非匹配成功,否则捕获变量 $1 等无效,并且它们也不会被清除。

#!/usr/bin/perl  
use warnings;
use strict;   
$_ = "bronto saurus burger";
if (/(?:bronto)? saurus (steak|burger)/)
{
    print "Fred wants a  $1";
}
else
{
    print "Fred dont wants a $1 $2";
}

在上面的示例中,为了避免在 $1 中捕获 bronto,使用了 (?:)

如果模式匹配,则将 $1 捕获为下一个分组模式。

因此,输出将如下所示:

Fred wants a burger

如果您不想保存匹配项,这很有用。

I think I would give you the answer. Don't use capture variables without checking that the match succeeded.

The capture variables, $1, etc, are not valid unless the match succeeded, and they're not cleared, either.

#!/usr/bin/perl  
use warnings;
use strict;   
$_ = "bronto saurus burger";
if (/(?:bronto)? saurus (steak|burger)/)
{
    print "Fred wants a  $1";
}
else
{
    print "Fred dont wants a $1 $2";
}

In the above example, to avoid capturing bronto in $1, (?:) is used.

If the pattern is matched , then $1 is captured as next grouped pattern.

So, the output will be as below:

Fred wants a burger

It is Useful if you don't want the matches to be saved.

夜雨飘雪 2024-09-22 06:34:52

打开 Google Chrome devTools,然后打开“控制台”选项卡:并输入以下内容:

"Peace".match(/(\w)(\w)(\w)/)

运行它,您将看到:

["Pea", "P", "e", "a", index: 0, input: "Peace", groups: undefined]

JavaScript RegExp 引擎捕获三个组,即索引为 1、2、3 的项目。现在使用非捕获标记来查看结果。

"Peace".match(/(?:\w)(\w)(\w)/)

结果是:

["Pea", "e", "a", index: 0, input: "Peace", groups: undefined]

这很明显什么是非捕获组。

Open your Google Chrome devTools and then Console tab: and type this:

"Peace".match(/(\w)(\w)(\w)/)

Run it and you will see:

["Pea", "P", "e", "a", index: 0, input: "Peace", groups: undefined]

The JavaScript RegExp engine capture three groups, the items with indexes 1,2,3. Now use non-capturing mark to see the result.

"Peace".match(/(?:\w)(\w)(\w)/)

The result is:

["Pea", "e", "a", index: 0, input: "Peace", groups: undefined]

This is obvious what is non capturing group.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文