正则表达式 - 匹配捕获组的可选重复模式

发布于 01-18 05:59 字数 916 浏览 2 评论 0原文

不知道如何确切地说这个问题的问题。甚至可能有一个更好的标题。我愿意接受建议。

我有以下主题:

(Field1 = 'Value1') and (Field2 = 'Value2')

(Field1 = 'Value1') and (Field2 = 'Value2') or (Field3 = 'Value3')

想以某种方式匹配()组之间的每一件事和组中的每个连词。因此,在第二个方面,

0: Field1 = 'Value1'
1: and
2: Field2 = 'Value2'
3: or
4: Field3 = 'Value3'

好消息的一些变化是,我有第一个适用于:

\(([A-Za-z0-9\s\'=]+)\) (and|or) \(([A-Za-z0-9\s\'=]+)\)

https://regex101.com/r/hmxaxs/1

但是(在第二个主题上)它与第三个“和()”不匹配。我需要支持任意数量的小组。我可以将其修改为仅查找“ and()”,但是它与第一个组不匹配。

我该如何告诉Regex这样做?我要么需要“双重计数”某些组(这很好),要么还有其他方法可以选择寻找其他模式并匹配它们。

感谢您的帮助!

PS:我能够使我的申请与正则code>(((和| or)\(([[A-ZA-Z0-9 \ s \'=]+)+)\))+>然后只接受第一组永远不会匹配并创建应用程序逻辑以支持这一点。不过,我敢打赌有一个更好的方法。

Appologies for not knowing exactly how to word this question. There is probably even a better title. I'm open to suggestions.

I have the following subjects:

(Field1 = 'Value1') and (Field2 = 'Value2')

and

(Field1 = 'Value1') and (Field2 = 'Value2') or (Field3 = 'Value3')

I want to match in such a way that I have each thing between the () in groups and each conjunction in a group. So, for the second one, some variation of

0: Field1 = 'Value1'
1: and
2: Field2 = 'Value2'
3: or
4: Field3 = 'Value3'

The good news is, I've got regex that works on the first:

\(([A-Za-z0-9\s\'=]+)\) (and|or) \(([A-Za-z0-9\s\'=]+)\)

https://regex101.com/r/hMXAXS/1

But (on the second subject) it doesn't match the third "and ()". I need to support arbitrary numbers of groups. I can modify it to just look for "and ()" but then it doesn't match the first group.

How can I tell regex to do this? I either need to "double count" some groups (which is fine) or have some other way of optionally looking for additional patterns and matching them.

Thanks for the help!

PS: I was able to get my application to work with the regex ((and|or) \(([A-Za-z0-9\s\'=]+)\))+ and then just accepting that the first group would never match and creating application logic to support this. Still, I'd bet there's a better way.

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

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

发布评论

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

评论(3

极度宠爱 2025-01-25 05:59:36

如果您可以每次匹配三组...

1 =键
2 =值
3 =连词动词,

那么此正则表达式也将允许该值中的括号。

/\((.*?) = '(.*?)'\) ?(and|or)?/gm

这会导致此字符串的这些匹配...

(field1 ='value1')和(field2 ='(在括号中)')和(field3 ='value3')

If you are OK with getting three groups per match...

1 = key
2 = value
3 = conjunction verb

Then this regex will also allow parenthesis in the value.

/\((.*?) = '(.*?)'\) ?(and|or)?/gm

Which results in these matches for this string...

(Field1 = 'Value1') and (Field2 = '(in parenthesis)') and (Field3 = 'Value3')

enter image description here

最好是你 2025-01-25 05:59:36

您可以在此处使用REGEX模式(?< = \()(。如下所示:

$input = "(Field1 = 'Value1') and (Field2 = 'Value2') or (Field3 = 'Value3')";
preg_match_all("/(?<=\()(.*?)(?=\))|(?:and|or)/", $input, $matches);
print_r($matches[0]);

此打印:

Array
(
    [0] => Field1 = 'Value1'
    [1] => and
    [2] => Field2 = 'Value2'
    [3] => or
    [4] => Field3 = 'Value3'
)

You may use preg_match_all here with the regex pattern (?<=\()(.*?)(?=\))|(?:and|or) as follows:

$input = "(Field1 = 'Value1') and (Field2 = 'Value2') or (Field3 = 'Value3')";
preg_match_all("/(?<=\()(.*?)(?=\))|(?:and|or)/", $input, $matches);
print_r($matches[0]);

This prints:

Array
(
    [0] => Field1 = 'Value1'
    [1] => and
    [2] => Field2 = 'Value2'
    [3] => or
    [4] => Field3 = 'Value3'
)
只有一腔孤勇 2025-01-25 05:59:36

如果您不担心括号表达式中可能存在分隔词或圆括号的边缘情况,则 preg_split() 会生成所需的平面数组。

代码: (演示)

$input = "(Field1 = 'Val and ue1') and (Field2 = 'Valu or e2') or (Field3 = 'Value3')";
var_export(
    preg_split(
        "~^\(|\)$|\) (and|or) \(~",
        $input,
        0,
        PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE
    )
);

输出:

array (
  0 => 'Field1 = \'Val and ue1\'',
  1 => 'and',
  2 => 'Field2 = \'Valu or e2\'',
  3 => 'or',
  4 => 'Field3 = \'Value3\'',
)

或者通过预先修剪最外面的括号来简化模式。 (演示

var_export(preg_split("~\) (and|or) \(~", trim($input, '()'), 0, PREG_SPLIT_DELIM_CAPTURE));

您还可以使用继续元字符 \G 继续从上一场比赛结束:(演示) 这需要 88 个步骤 与 Tim 的模式相比,后者需要 280 个步骤来解析字符串。

$input = "(Field1 = 'Val and ue1') and (Field2 = 'Valu or e2') or (Field3 = 'Value3')";
preg_match_all('~(?:^\(|\G(?!^)(?:\) | \())\K(?:(?:and|or)|[^)]+)~', $input, $m);
print_r($m[0]);

在提问者接受不提供问题中所述的输出数组结构的答案后进行编辑:(演示

preg_match_all("~\((\S+ = '.*?')\) ?(or|and)?~", $input, $m, PREG_SET_ORDER);
print_r($m);

此不检查连词后是否出现括号表达式。此外,在迭代匹配时,需要进行额外检查以查看是否声明了第三组 ([2])。

Array
(
    [0] => Array
        (
            [0] => (Field1 = 'Val and ue1') and
            [1] => Field1 = 'Val and ue1'
            [2] => and
        )

    [1] => Array
        (
            [0] => (Field2 = 'Valu or e2') or
            [1] => Field2 = 'Valu or e2'
            [2] => or
        )

    [2] => Array
        (
            [0] => (Field3 = 'Value3')
            [1] => Field3 = 'Value3'
        )
)

If you are not worried about fringe cases where delimiting words or paretheses can exist within the parenthetical expressions, then preg_split() generates the desired flat array.

Code: (Demo)

$input = "(Field1 = 'Val and ue1') and (Field2 = 'Valu or e2') or (Field3 = 'Value3')";
var_export(
    preg_split(
        "~^\(|\)$|\) (and|or) \(~",
        $input,
        0,
        PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE
    )
);

Output:

array (
  0 => 'Field1 = \'Val and ue1\'',
  1 => 'and',
  2 => 'Field2 = \'Valu or e2\'',
  3 => 'or',
  4 => 'Field3 = \'Value3\'',
)

Or simplify the pattern by pre-trimming the outermost parentheses. (Demo)

var_export(preg_split("~\) (and|or) \(~", trim($input, '()'), 0, PREG_SPLIT_DELIM_CAPTURE));

You can also use the continue metacharacter \G to continue matching from the end of the previous match: (Demo) This takes 88 steps versus Tim's pattern which takes 280 steps to parse the string.

$input = "(Field1 = 'Val and ue1') and (Field2 = 'Valu or e2') or (Field3 = 'Value3')";
preg_match_all('~(?:^\(|\G(?!^)(?:\) | \())\K(?:(?:and|or)|[^)]+)~', $input, $m);
print_r($m[0]);

Edit after the asker accepted an answer that does not provide the output array structure stated in the question: (Demo)

preg_match_all("~\((\S+ = '.*?')\) ?(or|and)?~", $input, $m, PREG_SET_ORDER);
print_r($m);

This does not check that a parenthetical expression occurs after a conjunction. Also, when iterating the matches an extra check will be required to see if the third group ([2]) is declared.

Array
(
    [0] => Array
        (
            [0] => (Field1 = 'Val and ue1') and
            [1] => Field1 = 'Val and ue1'
            [2] => and
        )

    [1] => Array
        (
            [0] => (Field2 = 'Valu or e2') or
            [1] => Field2 = 'Valu or e2'
            [2] => or
        )

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