正则表达式 - 替换开始和结束字符序列

时间:2015-10-19 18:37:01

标签: java regex

希望这是尝试解释我的目标的合理方式。

我的目标是从

更新字符串
"unchanged DETECT_OPEN blah DETECT_CLOSE unchanged"

"unchanged UPDATED_OPEN blah UPDATED_CLOSE unchanged"

所以

DETECT_OPEN = [
DETECT_CLOSE = ]

UPDATED_OPEN = <
UPDATED_CLOSE = >
输入字符串

上的

"this stays the same [i am wrapped] nothing to do here"

处理后

"this stays the same <i am wrapped> nothing to do here"

使用正则表达式解决这个问题有什么好方法吗? 我在java;所以java特定的例子是理想的;但任何正则表达式都是受欢迎的;我很乐意尝试从那里拿走它。

不确定它是否有任何区别;但是OPEN和CLOSE标记可以超过1个字符;并且长度不相等。

所以例如

DETECT_OPEN = ||
DETECT_CLOSE = |

简单示例:

 "this stays the same ||i am wrapped| nothing to do here"

我无法使用多次查找替换的原因 - 适用于

等场景
"this isn't an open || because it doesn't close. This open || is  closed |, this close | was never opened"

因此处理后会是

"this isn't an open || because it doesn't close. This open < is  closed >, this close | was never opened"

谢谢, 布伦特

3 个答案:

答案 0 :(得分:0)

你绝对要使用正则表达式吗?如果没有,更简单的解决方案是:

"this stays the same [i am wrapped] nothing to do here".replace("[","<").replace("]",">");

对于一般化的解决方案:

String target = "this stays the same OPEN i am wrapped CLOSE nothing to do here";
String DETECT_OPEN = "OPEN";
String DETECT_CLOSE = "CLOSE";
String UPDATED_OPEN = "REPLACED OPEN";
String UPDATED_CLOSE = "REPLACED CLOSE";

String replaced = target.replace(DETECT_OPEN, UPDATED_OPEN).replace(DETECT_CLOSE, UPDATED_CLOSE);

修改

这是为了回答您编辑过的问题。请注意,只要封闭分隔符不包含在开放分隔符中,此解决方案将适用于各种长度的分隔符。但是,它不会将打开的分隔符与封闭分隔符匹配。平衡括号问题比替换字符串要困难得多。可以找到代码示例here

由于平衡括号问题,我不建议使用正则表达式。

答案 1 :(得分:0)

这是一个在Apache commons StringUtils的帮助下提供的解决方案。 (如果不可用,您可以自己实现countMatches。)

import org.apache.commons.lang.StringUtils;

public class Brackets {
    final String DETECT_OPEN = "[";
    final String DETECT_CLOSE = "]";
    final String UPDATED_OPEN = "<";
    final String UPDATED_CLOSE = ">";

    public String matchingBrackets(String replaceMe) {
        int openCount = StringUtils.countMatches(replaceMe, DETECT_OPEN);
        int closeCount = StringUtils.countMatches(replaceMe, DETECT_CLOSE);
        if (openCount != closeCount) {
            // counts unequal, so return unchanged
            return replaceMe;
        }

        String ans = replaceMe;

        for (int i = 0; i < openCount; i++) {
            int nextOpenIndex = StringUtils.indexOf(ans, DETECT_OPEN);
            ans = StringUtils.replace(ans, DETECT_OPEN, UPDATED_OPEN);

            int lastCloseIndex = StringUtils.lastIndexOf(ans, DETECT_CLOSE);
            if (lastCloseIndex < nextOpenIndex) {
                // have reversed open and close, as in  )(
                return replaceMe;
            } else {
                ans = StringUtils.replace(ans, DETECT_CLOSE, UPDATED_CLOSE);
            }
        }
        return ans;
    }
}

这是一个testNG测试。

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import static org.testng.Assert.assertEquals;

public class BracketsTest {

    @Test(dataProvider = "BracketsTest")
    public void testMatchingBrackets(String expected, String processMe) throws Exception {
        Brackets brackets = new Brackets();
        assertEquals(expected, brackets.matchingBrackets(processMe));
    }

    @DataProvider
    public Object[][] BracketsTest() {
        return new Object[][]{
                {"][", "]["},
                {"<>", "[]"},
                {"An unmatched brace [ [] means no change", "An unmatched brace [ [] means no change"},
                {"this stays the same <i am wrapped> nothing to do here", "this stays the same [i am wrapped] nothing to do here"},
                {"this stays the same ]i am wrapped[ nothing to do here", "this stays the same ]i am wrapped[ nothing to do here"},
                {"the outer nested brackets < balance with these < inner >, and here's the outer > .", "the outer nested brackets [ balance with these [ inner ], and here's the outer ] ."},
                {"The left is <balanced> and so is the <right>.", "The left is [balanced] and so is the [right]."}
        };
    }
}

请注意,案例的行为略有不同:

the outer nested brackets [ balance with these [ inner ], and here's the outer ] .

我认为这些是平衡的,而OP认为它不是,可能是因为连续两个开放括号。

答案 2 :(得分:0)

您可以使用捕获组执行此操作:

String replaced = input.replaceAll("\\[(.*?)\\]", "<$1>");

这会创建一个新字符串,[...]替换为<...>$1是指模式中第一个匹配的(...)内捕获的表达式。