如何将捕获组与“\K”重置匹配一起使用?
How to use capture groups with the `\K` reset match?
我发现 this question 关于使用带有 \K
重置匹配的捕获组(即,不确定这是否是正确的名称),但它没有回答我的查询。
假设我有以下字符串:
ab
使用以下 regex
a\Kb
输出如预期的那样 b
:
但是,当使用 regex
(a\Kb)
添加捕获组(即 </code>)时,组 <code>
returns ab
而不是 a
:
给定以下字符串:
ab
cd
使用 regex
(a\Kb)|(c\Kd)
我希望组 </code> 包含 <code>b
,组 </code> 包含 <code>d
,但是情况并非如此,如下所示:
我试过了Wiktor Stribiżew's answer that points to using a branch reset group:
(?|a\Kb)|(?|c\Kd)
产生:
但是,现在比赛都是组 [=33=]
的一部分,而我要求它们分别属于组 </code> 和 <code>
。您对如何实现这一目标有任何想法吗?我正在使用 Oniguruma regular expressions and the PCRE
口味。
根据以下评论更新。
上面的示例旨在易于理解和重现。
@Booboo 指出 非捕获组 可以解决问题,即:
(?:a\K(b))|(?:c\K(d))
产生输出:
然而,当应用于另一个例子时它失败了。因此,为了清楚起见,我将这个问题扩展到涵盖评论中讨论的更复杂的场景。
假设我在 markdown
文件中有以下文本:
- [x] Example task. | Task ends. [x] Another task.
- [x] ! Example task. | This ends. [x] ! Another task.
This is a sentence. [x] Task is here.
Other text. Another [x] ! Task is here.
| | Task name | Plan | Actual | File |
| :---- | :-------------| :---------: | :---------: | :------------: |
| [x] | Task example. | 08:00-08:45 | 08:00-09:00 | [[task-one]] |
| [x] ! | Task example. | 08:00-08:45 | 08:00-09:00 | [[task-one]] |
我对带有 两个捕获组 的单个 regex
表达式感兴趣,如下所示:
组</code>(即,参见下面的选择):</p>
<ul>
<li><p>在 table 之外:捕获 <code>[x]
之后的所有内容(即不跟在 !
之后)直到 |
在 table 内:捕获 [x]
之后的所有内容(即不后跟 !
),不包括 |
符号
组</code>(即,见下面的选择):</p>
<ul>
<li><p>在table之外:捕获<code>[x] !
之后的所有内容,直到|
在 table 内:捕获 [x] !
之后的所有内容,不包括 |
符号
我有以下 regex
(即 see demo here)在单独评估时有效,但在捕获组内使用时无效:
- 组
</code>:
<ul>
<li>table外:<code>[^\|\s]\s*\[x\]\s*\K[^!|\n]*
- 在table里面:
(?:\G(?!\A)\||(?<=\[x]\s)\s*\|)\K[^|\n]*(?=\|)
组</code>:
<ul>
<li>table外:<code>[^\|\s]\s*\[x\]\s*\!\s*\K[^|\n]*
在table里面:(?:\G(?!\A)\||(?<=\[x]\s)\s*\!\s*\|)\K[^|\n]*(?=\|)
我遇到的问题是在组合上面的表达式时。
伪regex
:
([x] outside|[x] inside)|([x] ! outside|[x] ! inside)
实际regex
:
([^\|\s]\s*\[x\]\s*\K[^!|\n]*|(?:\G(?!\A)\||(?<=\[x]\s)\s*\|)\K[^|\n]*(?=\|))|([^\|\s]\s*\[x\]\s*\!\s*\K[^|\n]*|(?:\G(?!\A)\||(?<=\[x]\s)\s*\!\s*\|)\K[^|\n]*(?=\|))
产生(即,如 demo linked above):
table 内匹配的 regex
基于 Wiktor Stribiżew's answer and 。
如果我了解您要匹配的内容,请用作正则表达式:
(?:[^|\s]\s*\[x\](?!\s*!)\s*\K([^!|\n]*))|(?:[^|\s]\s*\[x\]\s*!\s*\K([^|\n]*))
我删除了一些不必要的转义。但此外:
对于 |
之前的第 1 组匹配(第一个备选方案),请注意,在我们匹配“[x]”之后,我有以下否定先行断言:
(?!\s*!)
这可确保 [x] 后不跟 0 个或多个空格后跟感叹号。只有这样,您才希望将下一个感叹号或换行符之前的所有内容都匹配为第 1 组。
而不是\K
,尝试使用控制动词(*SKIP)(*F)
:
(a(*SKIP)(*F)|b)|(c(*SKIP)(*F)|d)
检查test case。
以您在 regex101 上提供的示例为例,可以尝试使用以下表达式,但需要注意的是,文本不应包含除“[x]”以外的任何第三个括号
(?<!\|\s)(((?:\[x]\s[!]?))\K[^[\n]+)
解释以上内容
(?<!\|\s)
- 如您所述
,这种否定前瞻将丢弃 table
- (?:[x]\s[!]?)
- 这是一个非捕获组,将匹配“[x]”或“[x]!”
- \K (Optional)
- \K 重置报告匹配的起点。任何先前消耗的字符不再包含在最终匹配中
- [^[\n]+
- 在一次和无限次之间否定匹配前一个标记。
你可以使用
(?|(?:\G(?!\A)(?<=\|)|^\|\h*\[x\]\h*\|)\h*\K([^|\n]+)(?<=\S)\h*\||\[x]\h*\K([^|\s!]+(?:\h*[^|\s]+)*))|(?|(?:\G(?!\A)\||^\|\h*\[x]\h*!\h*\|)\h*\K([^|\n]+)(?<=\S)\h*|\[x]\h*!\h*\K([^|\s]+(?:\h*[^|\s]+)*))
见regex demo。 详情:
(?|(?:\G(?!\A)(?<=\|)|^\|\h*\[x\]\h*\|)\h*\K([^|\n]+)(?<=\S)\h*\||\[x]\h*\K([^|\s!]+(?:\h*[^|\s]+)*))
- 分支重置组匹配:
(?:\G(?!\A)(?<=\|)|^\|\h*\[x\]\h*\|)
- 非捕获组匹配
\G(?!\A)(?<=\|)
- 前一个成功匹配的结尾紧接 |
char
|
- 或者
^\|\h*\[x\]\h*\|
- line/string、|
的开始,零个或多个水平空格,[x]
,零个或多个水平空格,|
\h*\K
- 匹配后立即从匹配值中丢弃的零个或多个水平空格
([^|\n]+)(?<=\S)
- 第 1 组:除 LF 和 |
之外的一个或多个字符,尽可能多,但块应与非空白字符匹配
\h*\|
- 零个或多个水平空格和一个 |
字符
|
- 或
\[x]\h*\K
- [x]
,零个或多个水平空格,此文本从匹配值中丢弃
([^|\s!]+(?:\h*[^|\s]+)*)
- 第 1 组(注意它是一个分支重置组):除 !
、|
和空格之外的一个或多个字符,然后出现零次或多次零个或多个水平空格,然后是 |
和空格 以外的一个或多个字符
|
- 或
(?|(?:\G(?!\A)\||^\|\h*\[x]\h*!\h*\|)\h*\K([^|\n]+)(?<=\S)\h*|\[x]\h*!\h*\K([^|\s]+(?:\h*[^|\s]+)*))
- 分支重置组:
(?:\G(?!\A)\||^\|\h*\[x]\h*!\h*\|)
- 上一个成功匹配的结尾和后面的 |
个字符,或字符串的开头,|
,零个或多个水平空格,[x]
, !
包含零个或多个水平空格,一个 |
字符
\h*\K
- 零个或多个水平空格和到目前为止匹配的整个文本从匹配值中丢弃
([^|\n]+)(?<=\S)
- 第 2 组:除 LF 和 |
以非空白字符结尾的任何一个或多个字符
\h*
- 零个或多个水平空格
|
- 或
\[x]
- [x]
字符串
\h*!\h*\K
- !
包含零个或多个水平空格,并且到目前为止匹配的整个文本将从匹配值中丢弃
([^|\s]+(?:\h*[^|\s]+)*)
- 第 2 组(请注意它是一个分支重置组):除 |
和空格之外的一个或多个字符,然后零个或多个出现零个或多个水平空格和然后是 |
和空格以外的一个或多个字符。
我发现 this question 关于使用带有 \K
重置匹配的捕获组(即,不确定这是否是正确的名称),但它没有回答我的查询。
假设我有以下字符串:
ab
使用以下 regex
a\Kb
输出如预期的那样 b
:
但是,当使用 regex
(a\Kb)
添加捕获组(即 </code>)时,组 <code>
returns ab
而不是 a
:
给定以下字符串:
ab
cd
使用 regex
(a\Kb)|(c\Kd)
我希望组 </code> 包含 <code>b
,组 </code> 包含 <code>d
,但是情况并非如此,如下所示:
我试过了Wiktor Stribiżew's answer that points to using a branch reset group:
(?|a\Kb)|(?|c\Kd)
产生:
但是,现在比赛都是组 [=33=]
的一部分,而我要求它们分别属于组 </code> 和 <code>
。您对如何实现这一目标有任何想法吗?我正在使用 Oniguruma regular expressions and the PCRE
口味。
根据以下评论更新。
上面的示例旨在易于理解和重现。 @Booboo 指出 非捕获组 可以解决问题,即:
(?:a\K(b))|(?:c\K(d))
产生输出:
然而,当应用于另一个例子时它失败了。因此,为了清楚起见,我将这个问题扩展到涵盖评论中讨论的更复杂的场景。
假设我在 markdown
文件中有以下文本:
- [x] Example task. | Task ends. [x] Another task.
- [x] ! Example task. | This ends. [x] ! Another task.
This is a sentence. [x] Task is here.
Other text. Another [x] ! Task is here.
| | Task name | Plan | Actual | File |
| :---- | :-------------| :---------: | :---------: | :------------: |
| [x] | Task example. | 08:00-08:45 | 08:00-09:00 | [[task-one]] |
| [x] ! | Task example. | 08:00-08:45 | 08:00-09:00 | [[task-one]] |
我对带有 两个捕获组 的单个 regex
表达式感兴趣,如下所示:
组
</code>(即,参见下面的选择):</p> <ul> <li><p>在 table 之外:捕获 <code>[x]
之后的所有内容(即不跟在!
之后)直到|
在 table 内:捕获
[x]
之后的所有内容(即不后跟!
),不包括|
符号
组</code>(即,见下面的选择):</p>
<ul>
<li><p>在table之外:捕获<code>[x] !
之后的所有内容,直到|
在 table 内:捕获 [x] !
之后的所有内容,不包括 |
符号
我有以下 regex
(即 see demo here)在单独评估时有效,但在捕获组内使用时无效:
- 组
</code>: <ul> <li>table外:<code>[^\|\s]\s*\[x\]\s*\K[^!|\n]*
- 在table里面:
(?:\G(?!\A)\||(?<=\[x]\s)\s*\|)\K[^|\n]*(?=\|)
</code>:
<ul>
<li>table外:<code>[^\|\s]\s*\[x\]\s*\!\s*\K[^|\n]*
(?:\G(?!\A)\||(?<=\[x]\s)\s*\!\s*\|)\K[^|\n]*(?=\|)
我遇到的问题是在组合上面的表达式时。
伪regex
:
([x] outside|[x] inside)|([x] ! outside|[x] ! inside)
实际regex
:
([^\|\s]\s*\[x\]\s*\K[^!|\n]*|(?:\G(?!\A)\||(?<=\[x]\s)\s*\|)\K[^|\n]*(?=\|))|([^\|\s]\s*\[x\]\s*\!\s*\K[^|\n]*|(?:\G(?!\A)\||(?<=\[x]\s)\s*\!\s*\|)\K[^|\n]*(?=\|))
产生(即,如 demo linked above):
table 内匹配的 regex
基于 Wiktor Stribiżew's answer and
如果我了解您要匹配的内容,请用作正则表达式:
(?:[^|\s]\s*\[x\](?!\s*!)\s*\K([^!|\n]*))|(?:[^|\s]\s*\[x\]\s*!\s*\K([^|\n]*))
我删除了一些不必要的转义。但此外:
对于 |
之前的第 1 组匹配(第一个备选方案),请注意,在我们匹配“[x]”之后,我有以下否定先行断言:
(?!\s*!)
这可确保 [x] 后不跟 0 个或多个空格后跟感叹号。只有这样,您才希望将下一个感叹号或换行符之前的所有内容都匹配为第 1 组。
而不是\K
,尝试使用控制动词(*SKIP)(*F)
:
(a(*SKIP)(*F)|b)|(c(*SKIP)(*F)|d)
检查test case。
以您在 regex101 上提供的示例为例,可以尝试使用以下表达式,但需要注意的是,文本不应包含除“[x]”以外的任何第三个括号
(?<!\|\s)(((?:\[x]\s[!]?))\K[^[\n]+)
解释以上内容
(?<!\|\s)
- 如您所述 ,这种否定前瞻将丢弃 table
- (?:[x]\s[!]?)
- 这是一个非捕获组,将匹配“[x]”或“[x]!”
- \K (Optional)
- \K 重置报告匹配的起点。任何先前消耗的字符不再包含在最终匹配中
- [^[\n]+
- 在一次和无限次之间否定匹配前一个标记。
你可以使用
(?|(?:\G(?!\A)(?<=\|)|^\|\h*\[x\]\h*\|)\h*\K([^|\n]+)(?<=\S)\h*\||\[x]\h*\K([^|\s!]+(?:\h*[^|\s]+)*))|(?|(?:\G(?!\A)\||^\|\h*\[x]\h*!\h*\|)\h*\K([^|\n]+)(?<=\S)\h*|\[x]\h*!\h*\K([^|\s]+(?:\h*[^|\s]+)*))
见regex demo。 详情:
(?|(?:\G(?!\A)(?<=\|)|^\|\h*\[x\]\h*\|)\h*\K([^|\n]+)(?<=\S)\h*\||\[x]\h*\K([^|\s!]+(?:\h*[^|\s]+)*))
- 分支重置组匹配:(?:\G(?!\A)(?<=\|)|^\|\h*\[x\]\h*\|)
- 非捕获组匹配\G(?!\A)(?<=\|)
- 前一个成功匹配的结尾紧接|
char
|
- 或者^\|\h*\[x\]\h*\|
- line/string、|
的开始,零个或多个水平空格,[x]
,零个或多个水平空格,|
\h*\K
- 匹配后立即从匹配值中丢弃的零个或多个水平空格([^|\n]+)(?<=\S)
- 第 1 组:除 LF 和|
之外的一个或多个字符,尽可能多,但块应与非空白字符匹配\h*\|
- 零个或多个水平空格和一个|
字符
|
- 或\[x]\h*\K
-[x]
,零个或多个水平空格,此文本从匹配值中丢弃([^|\s!]+(?:\h*[^|\s]+)*)
- 第 1 组(注意它是一个分支重置组):除!
、|
和空格之外的一个或多个字符,然后出现零次或多次零个或多个水平空格,然后是|
和空格 以外的一个或多个字符
|
- 或(?|(?:\G(?!\A)\||^\|\h*\[x]\h*!\h*\|)\h*\K([^|\n]+)(?<=\S)\h*|\[x]\h*!\h*\K([^|\s]+(?:\h*[^|\s]+)*))
- 分支重置组:(?:\G(?!\A)\||^\|\h*\[x]\h*!\h*\|)
- 上一个成功匹配的结尾和后面的|
个字符,或字符串的开头,|
,零个或多个水平空格,[x]
,!
包含零个或多个水平空格,一个|
字符\h*\K
- 零个或多个水平空格和到目前为止匹配的整个文本从匹配值中丢弃([^|\n]+)(?<=\S)
- 第 2 组:除 LF 和|
以非空白字符结尾的任何一个或多个字符\h*
- 零个或多个水平空格
|
- 或\[x]
-[x]
字符串\h*!\h*\K
-!
包含零个或多个水平空格,并且到目前为止匹配的整个文本将从匹配值中丢弃([^|\s]+(?:\h*[^|\s]+)*)
- 第 2 组(请注意它是一个分支重置组):除|
和空格之外的一个或多个字符,然后零个或多个出现零个或多个水平空格和然后是|
和空格以外的一个或多个字符。