regex allMatches不完全匹配多个组

owfi6suc  于 2023-08-08  发布在  其他
关注(0)|答案(2)|浏览(86)

我以为我知道regex...情况是这样的:

N-U0 U0-M1
M1-T9 T9-R10 R10-E19
E19-L100 L100-B

字符串
我有一个String,它包含由空格分隔的组(我们称之为transitions)(可能是也可能不是换行符,我对它们一视同仁;也可以是一个或多个字符)。每个组由两个组组成(我们称之为exitingentering),由连字符分隔。其中每个都由单个字符(分别为NB)或特定字符和一位或多位数字组成。
我想运行一个正则表达式匹配,它将为每个transition给予一个对象,然后,对于每个对象,我想通过命名的捕获组访问transition的每个部分。
这些是我写的正则表达式:

static RegExp regex = RegExp(
  r'(?<exitingN>N)|((?<exitingF>[UMTREL]{1})(?<exitingNumber>[0-9]+))-(?<enteringB>B)|((?<enteringF>[UMTREL]{1})(?<enteringNumber>[0-9]+))\s+',
);

static RegExp exitingRegex = RegExp(
  r'(?<exitingN>N)|((?<exitingF>[UMTREL]{1})(?<exitingNumber>[0-9]+))-',
);

static RegExp enteringRegex = RegExp(
  r'-(?<enteringB>B)|((?<enteringF>[UMTREL]{1})(?<enteringNumber>[0-9]+))',
);


当我跑的时候

final matchList = regex.allMatches(
  "N-U0 U0-M1\nM1-T9 T9-R10 R10-E19\nE19-L100 L100-B\n",
);


它没有像我期望的那样工作。它匹配第一个N,然后是第一个U0,然后是第一个M1,依此类推,直到第一个L100B。我希望它匹配N-U0,然后是U0-M1等等。至少matchList.elementAt(0).namedGroup("exitingN")等工作,但我想要的exitingentering部分在一起。
我尝试在另一个组中添加正则表达式,我尝试了使用和不使用?:(使其不捕获),加上一些其他测试,我想,但没有任何效果。
然后我只测试了exitingRegex,它像预期的那样工作,匹配每一个exiting。但是enteringRegex不起作用。它匹配了除N之外的每个exiting和每个entering
我唯一能让它工作的方法是匹配exitingRegex,然后,对于entering,我必须首先使用"N-U0 U0-M1\nM1-T9 T9-R10 R10-E19\nE19-L100 L100-B\n".replaceAll(exitingRegex, "",),然后匹配enteringRegex,但没有前导连字符。通过这种方式,我分别得到了exitingentering,稍后我必须通过索引连接它们。
你在干什么?
先谢了。

xa9qqrwz

xa9qqrwz1#

要限制由|分隔的分支,请将它们 Package 在一个组中。此组可以是捕获组(())或非捕获组((?:)),具体取决于您的需要。也就是说,你的正则表达式应该看起来像这样:

(?:
  (?<exitingN>N)
|
  ((?<exitingF>[UMTREL])(?<exitingNumber>[0-9]+))
)
-
(?:
  (?<enteringB>B)
|
  ((?<enteringF>[UMTREL])(?<enteringNumber>[0-9]+))
)

字符串
对于U0-M1的输入,此正则表达式匹配并返回以下组:

  • 0:U0-M1
  • 2:U0
  • exitingFU
  • exitingNumber0
  • 等等

请注意,我删除了那些不必要的{1},因为默认情况下,表达式总是匹配其自身的一个示例。
试试on regex101.com

m528fe3b

m528fe3b2#

如果你不反对解析器,那么你可以在10分钟内得到必要的结果。
我的意思是花10分钟写一个解析器。
解析器代码更容易理解和改进。

import 'package:parser_combinator/parser/digit.dart';
import 'package:parser_combinator/parser/many1.dart';
import 'package:parser_combinator/parser/predicate.dart';
import 'package:parser_combinator/parser/skip_while.dart';
import 'package:parser_combinator/parser/tag.dart';
import 'package:parser_combinator/parser/take_while_m_n.dart';
import 'package:parser_combinator/parser/terminated.dart';
import 'package:parser_combinator/parser/tuple.dart';
import 'package:parser_combinator/parsing.dart';

void main(List<String> args) {
  const part = Tuple2(TakeWhileMN(1, 1, isAlpha), Digit());
  const element = Tuple3(part, Tag('-'), part);
  const groups = Many1(Terminated(element, SkipWhile(isWhitespace)));
  final result = parseString(groups.parse, input)
      .map((e) => (entering: e.$1, exiting: e.$3))
      .toList();
  print(result.join('\n'));
  final element4 = result[3];
  print('$element4');
  print('${element4.entering}  ${element4.exiting}');
  print('${element4.entering.$1} ${element4.entering.$2}');
}

const input = '''N-U0 U0-M1
M1-T9 T9-R10 R10-E19
E19-L100 L100-B''';

字符串
输出量:

(entering: (N, ), exiting: (U, 0))
(entering: (U, 0), exiting: (M, 1))
(entering: (M, 1), exiting: (T, 9))
(entering: (T, 9), exiting: (R, 10))
(entering: (R, 10), exiting: (E, 19))
(entering: (E, 19), exiting: (L, 100))
(entering: (L, 100), exiting: (B, ))
(entering: (T, 9), exiting: (R, 10))
(T, 9)  (R, 10)
T 9


此外,它解析得相当快。
在一台相当旧的计算机上,每秒75,000次迭代。

void main(List<String> args) {
  const count = 100000;
  final sw = Stopwatch();
  sw.start();
  for (var i = 0; i < count; i++) {
    const part = Tuple2(TakeWhileMN(1, 1, isAlpha), Digit());
    const element = Tuple3(part, Tag('-'), part);
    const groups = Many1(Terminated(element, SkipWhile(isWhitespace)));
    final result = parseString(groups.parse, input);
  }

  sw.stop();
  print('Iterations: $count, time: ${sw.elapsedMilliseconds / 1000} sec');
}


输出量:

Iterations: 100000, time: 1.305 sec

相关问题