如何编写正则表达式来匹配 ((11 3) (96 15) (2 3) )

发布于 2024-11-19 12:16:22 字数 430 浏览 2 评论 0原文

我正在尝试创建一个匹配的正则表达式:

((11 3) (96 15) (2 3) )

到目前为止我已经:

([^(|^)| |[A-Za-z])+

但它只捕获 11 而不是其余的。此外,该字符串更长,我只使用了其中的一小部分,因此它以相同的格式但不同的数字重复。 到目前为止,我对该计划的至少部分内容是这样的:

regex expression("([^(|^)| |[A-Za-z])+");
string line2 = "((11 3) (96 15) (2 3) )";
if(regex_match(line2, expression))
    cout << "yes";
else
    cout << "no";

I am trying to make a regular expression that will match:

((11 3) (96 15) (2 3) )

So far I have:

([^(|^)| |[A-Za-z])+

But it only captures the 11 and not the rest. Also the string is a lot longer I just used a small piece of it so it repeats with the same format but different numbers.
This what I have thus far for the program at least part of it:

regex expression("([^(|^)| |[A-Za-z])+");
string line2 = "((11 3) (96 15) (2 3) )";
if(regex_match(line2, expression))
    cout << "yes";
else
    cout << "no";

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

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

发布评论

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

评论(3

任谁 2024-11-26 12:16:22

您的示例字符串中有数字,但在正则表达式中使用字母,这是有意的吗?我想我会使用像这样的正则表达式:

\((\([0-9]+ [0-9]+\) )+\)

如果我们将其分解,这是我的思考过程:

\(     // start with a literal "("
(      // create a group
\(     // another literal "("
[0-9]+ // one or more digits
       // a space (hard to spell out here
[0-9]+ // one or more digits
       // a space (hard to spell out here
\)     // a litteral ")" to match the opening
)      // close the group
+      // group must repeat one or more times
\)     // final closing ")"

编辑: 好的,既然你说有时第二个数字不是数字,那么我们可以轻松地调整正则表达式,使其看起来像这样:

\((\([0-9]+ [A-Za-z0-9]+\) )+\)

如果您需要避免混合字母和数字,您可以这样做:

\((\[0-9]+ ([A-Za-z]+|[0-9]+)\) )+\)

You have numbers in your example string, but are using letters in your regex, was that intended? I suppose I would use a regex something like this:

\((\([0-9]+ [0-9]+\) )+\)

If we break it down, here's my thought process:

\(     // start with a literal "("
(      // create a group
\(     // another literal "("
[0-9]+ // one or more digits
       // a space (hard to spell out here
[0-9]+ // one or more digits
       // a space (hard to spell out here
\)     // a litteral ")" to match the opening
)      // close the group
+      // group must repeat one or more times
\)     // final closing ")"

EDIT: OK, since you say that sometimes the second numbers aren't numbers, then we can easily adjust the regex to look something like this:

\((\([0-9]+ [A-Za-z0-9]+\) )+\)

if you need to avoid mixing letters and numbers, you can do this:

\((\[0-9]+ ([A-Za-z]+|[0-9]+)\) )+\)
没有心的人 2024-11-26 12:16:22

让我们“从头开始”构建您的表达方式。

请记住您的最终目标是匹配 ((11 3) (96 15) (2 3) ),我们将从匹配一个更简单的模式开始,并一次前进一步:

\d        matches "1"
\d+       matches "11", or "3", or "96"
\d+ *\d+  matches "11 3" or "96 15"
\(\d+ *\d+\)           matches "(11 3)" or "(96 15)"
(\(\d+ *\d+\) *)*      matches "(11 3)(96 15) (2 3)"
\((\(\d+ *\d+\) *)*\)  matches "((11 3) (96 15) (2 3) )"

注意:我没有测试过这个答案。我依赖于 Boost.Regex文档来制定这个答案。

Let's build your expression "from the ground up".

Keeping in mind your final goal to match ((11 3) (96 15) (2 3) ), we shall start with matching a much simpler pattern, and advance one step at a time:

\d        matches "1"
\d+       matches "11", or "3", or "96"
\d+ *\d+  matches "11 3" or "96 15"
\(\d+ *\d+\)           matches "(11 3)" or "(96 15)"
(\(\d+ *\d+\) *)*      matches "(11 3)(96 15) (2 3)"
\((\(\d+ *\d+\) *)*\)  matches "((11 3) (96 15) (2 3) )"

Note: I have not tested this answer. I relied upon the Boost.Regex documentation to develop this answer.

遇见了你 2024-11-26 12:16:22

我最近在尝试匹配类似于 1-4,5,9,20-25 的语法时解决了这个问题。诚然,生成的正则表达式并不简单:

/\G([0-9]++)(?:-([0-9]++))?+(?:,(?=[-0-9,]+$))?+/

该表达式允许我逐步收集字符串中的所有匹配项。

我们可以对您的问题应用相同的方法,但是验证和匹配您给定的输入非常困难。 (我不知道该怎么做。如果其他人这样做,我想看看!)但是您可以单独验证输入:

/\(\s*(\s*((\s*\d+\s+\d+\s*)\)\s*)+\s*\)/

请参阅 Evan 的回答了解其工作原理。 \d 相当于 [0-9]\s 相当于 [\r\n\t ].

这是提取数字的增量匹配:

/\G\(?\s*(?:\(\s*(\d+)\s+(\d+)\s*\))(?:(?=\s*\(\s*\d+\s+\d+\s*\))|\s*\))/

它像这样分解:

/\G     # matches incrementally. \G marks the beginning of the string or the beginning of the next match.
 \(?\s* # matches first open paren; safely ignores it and following whiespace if this is not the first match.
 (?:    # begins a new grouping - it does not save matches.
   \(\s* # first subgroup open paren and optional whitespace.
   (\d+) # matches first number in the pair and stores it in a match variable.
   \s+   # separating whitespace
   (\d+) # matches second number in the pair and stores it in a match variable.
   \s*\) # ending whitespace and close paren
 )      # ends subgroup
 (?:    # new subgroup
   (?=  # positive lookahead - this is optional and checks that subsequent matches will work.
     \s*\(\s*\d+\s+\d+\s*\)  # look familiar?
   )    # end positive lookahead
   |    # if positive lookahead fails, try another match
   \s*\)\s* # optional ending whitespace, close paren
 )/     # ... and end subgroup.

我还没有测试过这个,但我相信它会起作用。每次将表达式应用于给定字符串时,它都会提取后续的每一对数字,直到看到最后一个右括号,并且它将消耗整个字符串,或者在出现输入错误时停止。您可能需要对 Boost::regex 进行巧妙处理。这是一个与 Perl 兼容的正则表达式。

I solved this recently when trying to match syntax similar to 1-4,5,9,20-25. The resulting regular expression is, admittedly, not simple:

/\G([0-9]++)(?:-([0-9]++))?+(?:,(?=[-0-9,]+$))?+/

This expression allowed me to collect all of the matches in the string, incrementally.

We can apply the same approach to your problem, but it's extremely difficult to both validate and match your given input. (I don't know how to do it. If someone else does, I'd like to see!) But you can validate the input separately:

/\(\s*(\s*((\s*\d+\s+\d+\s*)\)\s*)+\s*\)/

See Evan's answer for how it works. \d is equivalent to [0-9] and \s is equivalent to [\r\n\t ].

This is an incremental match to extract the numbers:

/\G\(?\s*(?:\(\s*(\d+)\s+(\d+)\s*\))(?:(?=\s*\(\s*\d+\s+\d+\s*\))|\s*\))/

It breaks down like so:

/\G     # matches incrementally. \G marks the beginning of the string or the beginning of the next match.
 \(?\s* # matches first open paren; safely ignores it and following whiespace if this is not the first match.
 (?:    # begins a new grouping - it does not save matches.
   \(\s* # first subgroup open paren and optional whitespace.
   (\d+) # matches first number in the pair and stores it in a match variable.
   \s+   # separating whitespace
   (\d+) # matches second number in the pair and stores it in a match variable.
   \s*\) # ending whitespace and close paren
 )      # ends subgroup
 (?:    # new subgroup
   (?=  # positive lookahead - this is optional and checks that subsequent matches will work.
     \s*\(\s*\d+\s+\d+\s*\)  # look familiar?
   )    # end positive lookahead
   |    # if positive lookahead fails, try another match
   \s*\)\s* # optional ending whitespace, close paren
 )/     # ... and end subgroup.

I haven't tested this, but I'm confident it'd work. Each time you apply the expression to a given string, it'll extract each subsequent pair of numbers until it sees the last closing paren, and it'll consume the whole string, or stop if there's an input error. You may need to finesse it for Boost::regex. This is a Perl-compatible regular expression.

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