【问题标题】:How to remove unnecessary parenthesis?如何删除不必要的括号?
【发布时间】:2019-12-16 01:27:26
【问题描述】:

this 相同,但使用的是 JavaScript。几个例子来说明我的目标:

  • ((((foo))) => (foo)
  • ((foo)) => (foo)
  • (foo) => (foo)
  • (foo (bar)) => (foo (bar))
  • ((foo b)ar) => ((foo b)ar)
  • (((a)b(c))) => ((a)b(c))

我已经创建了一个正则表达式,它应该与我想要更改的 /\({2,}[\s\S]*\){2,}/g 匹配,但我似乎无法弄清楚如何删除它们。

String.replace(/\({2,}[\s\S]*\){2,}/g, '(${rest})')之类的吗?

【问题讨论】:

  • 前 3 个示例是微不足道的,但后 2 个不能单独使用正则表达式。
  • 当正则表达式是你的锤子时,一切看起来都像拇指。

标签: javascript regex replace


【解决方案1】:

你可以试试这个:

'(((foo))) => (foo)'.replace(/(\({2,})([a-zA-Z]*)(\){2,})/g, '($2)')

或者一般形式:

str.replace(/(\({2,})([a-zA-Z]*)(\){2,})/g, '($2)')

我稍微更改了您的正则表达式以将正则表达式匹配的文本捕获为编号组,因此可以在string.replace() 中使用反向引用。

所以基本上你有 3 个组,你可以参考它们:

  • $1 将是左括号,例如 ((、((( 等)。
  • $2 是 ((( content ))) 之间的内容
  • $3 将是右括号,如 ))、))) 等。

黑客愉快:)

【讨论】:

  • 失败例如((((a))b))。诀窍是,结束组的长度必须与开始组相同。单独使用正则表达式无法解决。
  • @georg 你能提供一个替代解决方案吗?另一个没有涉及的场景是((a)+(b))
  • @MiXT4PE:添加
【解决方案2】:

应该这样做。

function RemoveDuplicateParenthesis(str) {
  var l = -1;
  while (l != str.length) {
    l = str.length;
    str = str.replace(/\({2,}.*\){2,}/igm, function(s) {
      var start = s.match(/^\(+/igm)[0].length;
      var end = s.match(/\)+$/igm)[0].length;
      s = s.replace(new RegExp("^\\({" + Math.min(start, end) + "}", 'igm'), '(');
      s = s.replace(new RegExp("\\){" + Math.min(start, end) + "}$", 'igm'), ')');
      return s;
    });
  }
  return str;
}
//Test
var pre = document.body.appendChild(document.createElement("pre"));
var inputs = ['(((foo)))',
  '((foo))',
  '(foo)',
  '(foo (bar))',
  '((foo b)ar)',
  '(((foo b)ar))',
  '((foo (b)ar))',
  '((fo(o ((b)))ar))'
];
pre.textContent = JSON.stringify(inputs.map(function(s) {
  return {
    original: s,
    fixed: RemoveDuplicateParenthesis(s)
  };
}), null, 4);

【讨论】:

  • ((a)+(b)) 变成(a)+(b)。您的预期输出是什么?
  • ((a)+(b)) 是预期的输出,因为两个括号都有作用。同样(((a)+(b))) 应该变成((a)+(b))
【解决方案3】:

我建议您尝试经典的 tokenize-parse-generate 工作流程,而不是与正则表达式作斗争。想法是将字符串解析为数据结构(在本例中为嵌套数组),简化该结构并从中生成一个新字符串。

例子:

function tokenize(str) {
    return str.match(/[()]|[^()]+/g);
}

function parse(toks, depth = 0) {
    let ast = [];

    while (toks.length) {
        let t = toks.shift();
        
        switch (t) {
            case '(':
                ast.push(parse(toks, depth + 1));
                break;
            case ')':
                if (!depth)
                    throw new SyntaxError('mismatched )');
                return ast;
            default:
                ast.push(t);
        }
    }

    if (depth) {
        throw new SyntaxError('premature EOF');
    }

    return ast;
}

function generate(el) {
    if (!Array.isArray(el))
        return el;

    while (el.length === 1 && Array.isArray(el[0]))
        el = el[0];

    return '(' + el.map(generate).join('') + ')';
}


//

let test = `
(((foo)))
((foo))
(foo)
(foo (bar))
((foo b)ar)
((((foo)) bar))
((((((foo))bar))baz))
((((((((foo))))))))
foo
`;

for (let s of test.trim().split('\n'))
    console.log(s, '=>', generate(parse(tokenize(s))));

【讨论】:

    猜你喜欢
    • 2015-10-05
    • 2023-02-02
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 2012-03-31
    相关资源
    最近更新 更多