Matlab 正则表达式捕获具有命名标记的组

Matlab regular expressions capture groups with named tokens

我正在尝试从 matlab 中的文件中读取几行文本。使用 regexp 函数提取一些命名标记。虽然在 Octave 中一切都很好,但我无法在 Matlab 中使用相同的表达式。

我想处理不同类型的行,例如:

line1 = 'attr enabled  True';
line2 = 'attr width  1.2';
line3 = 'attr size  8Byte';

我想出的正则表达式如下所示:

pattern = '^attr +(?<name>\S+) +(?:(?<number>[+-]?\d+(?:\.\d+)?)(?<unit>[a-z,A-z]*)?|(?<bool>(?:[tT][rR][uU][eE]|[fF][aA][lL][sS][eE])))$'

当我运行(在 Matlab 2016b 中):

[tokens, matches] = regexp(line1, pattern, 'names', 'match');

结果如下:

tokens  = 0×0 empty struct array with fields:
             name
matches = 0×0 empty cell array

然而,八度音阶的结果看起来像:

tokens = scalar structure containing the fields:
             name = enabled
             number =
             unit =
             bool = True
matches = { [1,1] = attr enabled  True }

我用 regexr.com 测试了我的正则表达式,这表明八度音阶工作正常。

一旦我从正则表达式模式中删除外部捕获组:

pattern = '^attr +(?<name>\S+) +(?<number>[+-]?\d+(?:\.\d+)?)(?<unit>[a-z,A-z]*)?|(?<bool>(?:[tT][rR][uU][eE]|[fF][aA][lL][sS][eE]))$'

Matlab 输出:

tokens = struct with fields:
              bool: 'True'
              name: []
              number: []
              unit: []
matches = { True }

所以 matlab 开始将其他命名标记识别为字段,但名称字段仍然是空的。而且正则表达式不再是正确的交替...... 这是关于捕获组的错误还是我误解了什么?

一些简单的测试表明 MATLAB 不支持具有命名参数的嵌套非捕获组。最好的解决方法可能是使用未命名的组?

x1 = 'Apple Banana Cat';

% Named groups work:
re1 = regexp(x1, '(?<first>A.+) (?<second>B.+) (?<third>C.+)', 'names')

% Non-capturing (unnamed) groups work...
re2 = regexp(x1, '(?:A.+) (?<second>B.+) (?<third>C.+)', 'names')

% Nested non-capturing group does work, but not with named groups
re3 = regexp(x1, '(?:(A.+)) (?<second>B.+) (?<third>C.+)', 'names')         % OK
re4 = regexp(x1, '(?:(A.+)) (B.+) (C.+)', 'tokens')                         % OK (unnamed)
re5 = regexp(x1, '(?:(?<first>A.+)) (?<second>B.+) (?<third>C.+)', 'names') % Not OK

遗憾的是没有单一的规范正则表达式定义,有很多种。因此,仅仅因为它与 Octave 或 regexr.com 一起工作并不能保证它会或应该在其他地方工作,特别是当你开始进入正则表达式的更奇特的区域时。

我认为您可能需要解决这个问题,尽管我很高兴被证明是错误的!

(PS 我在 v2016a 中测试,YMMV)。

编辑: 我现在已经在 2016a 和 2016b 中进行了测试 "re4" 并且在两者中都给出了相同的结果:

>> x1 = 'Apple Banana Cat';
>> re4 = regexp(x1, '(?:(A.+)) (B.+) (C.+)', 'tokens');

>> disp(re4{1}{1})
Banana

>> disp(re4{1}{2})
Cat

嵌套捕获组将是这里的问题。

我运行也遇到了这个问题,这让我很抓狂。最后我想我找到了解释发生了什么的 Matlab 文档:

Note: If an expression has nested parentheses, MATLAB captures tokens that correspond to the outermost set of parentheses. For example, given the search pattern '(and(y|rew))', MATLAB creates a token for 'andrew' but not for 'y' or 'rew'.

来自 "Regular Expressions" Matlab 文档的帮助文件:

>> web(fullfile(docroot, 'matlab/matlab_prog/regular-expressions.html#btrvwd4'))

我是 运行 版本 8.6.0.267246 (R2015b)

所以这是 non-feature,特别是 Matlab。对我来说似乎非常有限,但也许我错过了一些东西。