使用java查找和替换没有标记

时间:2014-08-07 04:55:59

标签: java regex

我很确定这是被问到的&回答,但我找不到答案,所以我会问:

我想使用javas regex来查找和替换。没有涉及标记(没有,源代码字符串中的“$ {ImMarkup!}”,我希望替换的值是上下文化的(因为,我不能用B写一个简单的替换A)。

示例使一切变得更容易,这里是一些示例代码。这是源字符串:

! locator's position P1(p1x,p1y),P2(p2x,p2y)
R,1,0.001,0.001,0.001,0.001, , ,
RMORE, , , ,
RMORE   
RMORE, ,
ET,MPTEMP,,,,EX, x1=38000
x2 = 2345
MPTEMP,,,,,,,,  
MPTEMP,1,0  
MPDATA,EX,1,,38000*6894.75

我的正则表达式是

 +(?<variableName>\w+) *= *-?(?<variableValue>\d+\.?\d*)

(注意第一个加号前的空格)

我希望用“x1 = 100”代替“x1 = 38000”,用“x2 = 200”代替“x2 = 2345”

输出

...
RMORE, ,
ET,MPTEMP,,,,EX, x1=100
x2 = 200
MPTEMP,,,,,,,,  
...

我在这里创建了一个包含一些半可运行代码的要点(它使用了我们的公共代码库中的一些东西,但它可以跟随:https://gist.github.com/Groostav/acf5b584078813e7cbe6

我得到的代码大致是

String regex = "+(?<variableName>\\w+) *= *-?(?<variableValue>\\d+\\.?\\d*)"
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(sourceText);

while(matcher.find()){

    String variableName = matcher.group("variableName");
    String existingValue = matcher.group("variableValue");

    int newValue;
    switch(variableName){
        case "x1": newValue = 100; break;
        case "x2": newValue = 200; break;
        default: throw new IllegalStateException();
    }

    matcher.appendReplacement(output, "" + newValue);

}

matcher.appendTail(output);

正则表达式本身有效:它捕获我需要的值,我可以通过matcher.group(“variableName”)和matcher.group(“variableValue”)访问它们,我遇到的问题是写使用java regex API返回'variableValue'的新值。

在上面的例子中,matcher.group(“variableValue”)不会保持任何状态,所以我似乎无法指定我不想替换整行的appendReplacement()方法,而是简单地< / em>第二个捕获组。

值得研究,x1和x2不是硬性运行时名称,所以我不能简单地将它干酪化并为x1和x2分别编写查找和替换字符串。我需要runtime \ w +来查找变量名。

所以我可以针对第一个结果运行另一个正则表达式,这次只捕获值,但这并不漂亮,并且它需要我用StringBuilder / Buffer来捏造索引值,而不是那个好的索引 - 免费调用matcher.appendTail。

PS:你在上面看到的语言被称为“ANSYS参数化设计语言(APDL)”,我无法找到该语法的语法。如果你们中的任何一个人知道一个人在哪里,我会非常感激。

感谢阅读。

2 个答案:

答案 0 :(得分:1)

您可以使用此正则表达式:

(\w+\s*)=(\s*\d+)

<强> Working demo

检查替换部分。您可以使用相同的方法替换所需的内容,就像使用捕获组索引一样。

答案 1 :(得分:0)

我的Hacky解决方案似乎有效,是手动遍历我们的解析树,沿着rhs,并替换新值。这很烦人,因为它需要我重构我的正则表达式并完成手工工作,但它确实可以完成这项工作,我相信它的可靠性:

// semi-formally, APDL seems to define:
// AssignmentExpression     -> QualifiedIdentifier = Expression
// QualifiedIdentifier      -> SPACE+ Identifier SPACE*
// Expression               -> SPACE* Value  //Value is captured as "value"
// Identifier               -> [A-Za-z0-9]*  //Identifier is captured as "identifier"
// Value                    -> [0-9]* (DOT [0-9]*)?

private static final String rValue = "\\d+(\\.\\d*)?";
private static final String rIdentifier = "(?<identifier>\\w+)";
private static final String rQualifiedIdentifier = " +" + rIdentifier + " *";
private static final String rExpression = " *-?(?<value>" + rValue + ")";

private static final String rAssignmentExpression = rQualifiedIdentifier + "=" + rExpression;


@Test
public void when_scanning_using_our_regex(){
    Pattern assignmentPattern = Pattern.compile(rAssignmentExpression);
    Pattern rhsPattern =        Pattern.compile("=" + rExpression);
    Pattern valuePattern =      Pattern.compile(rValue);

    Matcher assignmentMatcher = assignmentPattern.matcher(sourceText);

    StringBuffer output = new StringBuffer();
    int newValue = 20;

    while(assignmentMatcher.find()){
        String assignment = assignmentMatcher.group();
        Matcher rhsMatcher = rhsPattern.matcher(assignment);
        assert rhsMatcher.find() : "couldn't find an RHS in an the assignment: '" + assignment + "'?";
        String oldRhs = rhsMatcher.group();
        Matcher valueMatcher = valuePattern.matcher(oldRhs);
        assert valueMatcher.find() : "couldn't find a value in an RHS: '" + oldRhs + "'?";

        String oldValue = valueMatcher.group();
        String newRhs = oldRhs.replace(oldValue, "" + newValue);
        String newAssignment = assignment.replace(oldRhs, newRhs);

        assignmentMatcher.appendReplacement(output, "" + newAssignment);
    }

    assignmentMatcher.appendTail(output);

    System.out.println(output.toString());

}