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。对我来说似乎非常有限,但也许我错过了一些东西。
我正在尝试从 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。对我来说似乎非常有限,但也许我错过了一些东西。