正则表达式计入Lookbehind

时间:2016-12-20 19:01:29

标签: regex matlab expression regex-lookarounds lookbehind

我正在尝试以下方法:我有一个字符串,看起来像这样: 'a,b,(c,d,(e,f),g),(h,i)' 我想把它分成类似第一层的逗号:

a b(c,d,(e,f),g)(h,i)

我无法弄清楚如何做到这一点。我得到的逻辑解决方案是,我必须找到逗号,它们后面有相同数量的左右括号。如何用正则表达式实现它?

最好的问候

3 个答案:

答案 0 :(得分:1)

没有正则表达式的解决方案:

a = 'a, b, (c, d, (e, f), g), (h, i)';
a(cumsum((a=='(')-(a==')'))==0 & a==',')=';'
out = strsplit(a, ';')

结果:

{
  [1,1] = a
  [1,2] =  b
  [1,3] =  (c, d, (e, f), g)
  [1,4] =  (h, i)
}

我们可以使用

找到每个角色的嵌套级别
cumsum((a=='(')-(a==')'));

嵌套级别数组:

0000001111111222221111000111110

所以例如前6个字符'a, b, '处于第0级,依此类推 我们只需要那些0级的字符

cumsum((a=='(')-(a==')'))==0

也应该是逗号

cumsum((a=='(')-(a==')'))==0 & a==','

将0级别的所有逗号设置为';'

a(cumsum((a=='(')-(a==')'))==0 & a==',')=';'

并拆分字符串

strsplit(a, ';')

答案 1 :(得分:0)

以下是几个选项:

选项1:如果您的数据在行之间具有一致的逗号和括号模式,您实际上可以使用a regex轻松解析它。缺点是,如果您的模式发生变化,您必须更改正则表达式。但它也很快(即使对于非常大的单元阵列):

str = {'(0, 0, 1540.4, (true, (121.96, 5)), 5.7068, 1587.0)';
       '(0, 0, 1537.5, (true, (121.93, 6)), 5.7068, 1587.0)';
       '(0, 0, 1537.5, (true, (121.93, 3)), 5.7068, 1587.0)';
       '(0, 0, 1537.5, (true, (121.93, 4)), 5.7068, 1587.0)';
       '(0, 0, 1537.5, (true, (121.93, 5)), 6.0965, 1587.0)';
       '(0, 0, 1535.2, (true, (121.9, 6)), 6.0965, 1587.0)';
       '(0, 0, 1535.2, (true, (121.9, 3)), 6.0965, 1587.0)';
       '(0, 0, 1535.2, (true, (121.9, 4)), 6.0965, 1587.0)';
       '(0, 0, 1535.2, (true, (121.9, 5)), 6.3782, 1587.0)';
       '(0, 0, 1532.3, (true, (121.87, 6)), 6.3782, 1587.0)'};

tokens = regexp(str, ['^\(([-\d\.]+), ' ... % Column 1
                         '([-\d\.]+), ' ... % Column 2
                         '([-\d\.]+), ' ... % Column 3
                         '(\(\w+, \([-\d\.]+, [-\d\.]\)\)), ' ... % Column 4
                         '([-\d\.]+), ' ... % Column 5
                         '([-\d\.]+))'], ... % Column 6
                'tokens', 'once');
str = vertcat(tokens{:});
disp(str);

这个例子的结果是:

'0'    '0'    '1540.4'    '(true, (121.96, 5))'    '5.7068'    '1587.0'
'0'    '0'    '1537.5'    '(true, (121.93, 6))'    '5.7068'    '1587.0'
'0'    '0'    '1537.5'    '(true, (121.93, 3))'    '5.7068'    '1587.0'
'0'    '0'    '1537.5'    '(true, (121.93, 4))'    '5.7068'    '1587.0'
'0'    '0'    '1537.5'    '(true, (121.93, 5))'    '6.0965'    '1587.0'
'0'    '0'    '1535.2'    '(true, (121.9, 6))'     '6.0965'    '1587.0'
'0'    '0'    '1535.2'    '(true, (121.9, 3))'     '6.0965'    '1587.0'
'0'    '0'    '1535.2'    '(true, (121.9, 4))'     '6.0965'    '1587.0'
'0'    '0'    '1535.2'    '(true, (121.9, 5))'     '6.3782'    '1587.0'
'0'    '0'    '1532.3'    '(true, (121.87, 6))'    '6.3782'    '1587.0'

请注意,我使用模式[-\d\.]+来匹配可能带有负号或小数点的任意数字。

选项2:您可以使用regexprep重复删除不包含其他括号的括号对,将其替换为空格以保持相同大小的字符串。然后,在最终处理的字符串中找到逗号的位置,并使用这些位置分解原始字符串。您不必为每个新的逗号和圆括号模式更改正则表达式,但这将比上面稍微慢一些(但对于最多15,000个单元格的数组仍然只需要一两秒):

% Using raw str from above:
str = cellfun(@(s) {s(2:end-1)}, str);
tempStr = str;
modStr = regexprep(tempStr, '(\([^\(\)]*\))', '${blanks(numel($0))}');
while ~isequal(modStr, tempStr)
  tempStr = modStr;
  modStr = regexprep(tempStr, '(\([^\(\)]*\))', '${blanks(numel($0))}');
end

commaIndex = regexp(tempStr, ',');
str = cellfun(@(v, s) {mat2cell(s, 1, diff([1 v numel(s)+1]))}, commaIndex, str);
str = strtrim(strip(vertcat(str{:}), ','));
disp(str);

这与选项1的结果相同。

答案 2 :(得分:0)

我知道问题是如何使用正则表达式实现它,但如果你是逐个字符地解析它,你可以随时跟踪嵌套级别。这是一个javascript片段,用于演示如何完成(https://jsfiddle.net/jf65k0jc/):

var str = 'a, b, (c, d, (e, f), g), (h, i)';
var arr = [];
var buffer = '';
var level = 0;
for (var i = 0; i < str.length; i++) {
  var letter = str[i];

  if (level === 0) {
    if (letter === ',') {
      arr.push(buffer.trim());
      buffer = '';
    }
    else {
      buffer += letter;
      if (letter === '(') {
        level++;
      }
    }
  }
  else {
    buffer += letter;
    if (letter === '(') {
      level++;
    }
    else if (letter === ')') {
      level--;
    }
  }
}
arr.push(buffer.trim());

var output = '';
for (var i = 0; i < arr.length; i++) {
  output += arr[i] + '<br>';
}
$('.output').html(output);

// Outputs:
// a
// b
// (c, d, (e, f), g)
// (h, i)