代码之家  ›  专栏  ›  技术社区  ›  Humphrey Bogart

用于拆分嵌套坐标字符串的正则表达式

  •  10
  • Humphrey Bogart  · 技术社区  · 16 年前

    我有一个字符串的格式 "[(1, 2), (2, 3), (3, 4)]" ,具有任意数量的元素。我试着用逗号分隔坐标,也就是说,检索 (1, 2) , (2, 3) ,及 (3, 4) .

    6 回复  |  直到 16 年前
        1
  •  7
  •   Community Mohan Dere    9 年前

    你可以用 String#split() 为了这个。

    String string = "[(1, 2), (2, 3), (3, 4)]";
    string = string.substring(1, string.length() - 1); // Get rid of braces.
    String[] parts = string.split("(?<=\\))(,\\s*)(?=\\()");
    for (String part : parts) {
        part = part.substring(1, part.length() - 1); // Get rid of parentheses.
        String[] coords = part.split(",\\s*");
        int x = Integer.parseInt(coords[0]);
        int y = Integer.parseInt(coords[1]);
        System.out.printf("x=%d, y=%d\n", x, y);
    }
    

    这个 (?<=\\)) positive lookbehind 意味着它前面必须有 ) (?=\\() positive lookahead ( . 这个 (,\\s*) 意味着它必须在 , 以及之后的任何空间。这个 \\

    也就是说,特定字符串可以识别为 List#toString()

    更新 根据评论,您确实也可以采用另一种方法,去掉非数字:

    String string = "[(1, 2), (2, 3), (3, 4)]";
    String[] parts = string.split("\\D.");
    for (int i = 1; i < parts.length; i += 3) {
        int x = Integer.parseInt(parts[i]);
        int y = Integer.parseInt(parts[i + 1]);
        System.out.printf("x=%d, y=%d\n", x, y);
    }
    

    \\D 意味着它必须在任何 不 \\d 代表数字)。这个 . after意味着它应该消除数字后面的任何空白匹配。但我必须承认,我不知道如何消除空白匹配 之前

    毕竟,最终还是使用 分析器 为了这个。 See Huberts answer on this topic .

        2
  •  9
  •   h7r    8 年前

    来自Java5

    Scanner sc = new Scanner();
    sc.useDelimiter("\\D+"); // skip everything that is not a digit
    List<Coord> result = new ArrayList<Coord>();
    while (sc.hasNextInt()) {
        result.add(new Coord(sc.nextInt(), sc.nextInt()));
    }
    return result;
    

    coords .

        3
  •  3
  •   Bart Kiers    16 年前

    如果不需要表达式来验证语法 坐标,这应该是:

    \(\d+,\s\d+\)
    

    此表达式将返回多个匹配项(三个与示例中的输入匹配)。

    在你的问题中,你声明你想“检索” (1, 2) (2, 3) ,及 (3, 4) . 如果您实际需要与每个坐标关联的一对值,则可以删除括号并修改正则表达式以执行一些捕获:

    (\d+),\s(\d+)
    

    Java代码如下所示:

    import java.util.regex.*;
    
    public class Test {
        public static void main(String[] args) {
            Pattern pattern = Pattern.compile("(\\d+),\\s(\\d+)");
            Matcher matcher = pattern.matcher("[(1, 2), (2, 3), (3, 4)]");
    
            while (matcher.find()) {
                int x = Integer.parseInt(matcher.group(1));
                int y = Integer.parseInt(matcher.group(2));
                System.out.printf("x=%d, y=%d\n", x, y);
            }
        }
    }
    
        4
  •  1
  •   Bill K    16 年前

    如果您使用regex,您将得到糟糕的错误报告,并且如果您的需求发生变化(例如,如果您必须将不同方括号中的集合解析为不同的组),事情将变得更加复杂。

    我建议您只需手工编写解析器,它就像10行代码,不应该太脆弱。跟踪您正在做的每件事,打开括号、关闭括号、打开大括号&关闭支架。它就像一个带有5个选项(和一个默认值)的switch语句,真的没那么糟糕。

    对于最小的方法,可以忽略开括号和开括号,因此实际上只有3种情况。


    这将是熊的最低限度。

    // Java-like psuedocode
    int valuea;
    String lastValue;
    tokens=new StringTokenizer(String, "[](),", true);
    
    for(String token : tokens) {  
    
        // The token Before the ) is the second int of the pair, and the first should
        // already be stored
        if(token.equals(")"))
            output.addResult(valuea, lastValue.toInt());
    
        // The token before the comma is the first int of the pair
        else if(token.equals(",")) 
            valuea=lastValue.toInt();
    
        // Just store off this token and deal with it when we hit the proper delim
        else
            lastValue=token;
    }
    

    作为可扩展性的一个示例,如果必须将不同的方括号分隔组集放入不同的输出集中,那么添加操作非常简单:

        // When we close the square bracket, start a new output group.
        else if(token.equals("]"))
            output.startNewGroup();
    

    检查paren就像创建一堆字符一样简单,并将每个字符(或(在堆栈上,然后当您得到一个)或(或)时)弹出堆栈并断言它匹配。此外,完成后,请确保stack.size()==0。

        5
  •  1
  •   dplante Tschallacka    14 年前

    是否总是需要分析3组坐标?

    \[(\(\d,\d\)), (\(\d,\d\)), (\(\d,\d\))\]

        6
  •  0
  •   Yaakov Shoham    16 年前

    在正则表达式中,可以在 (?<=\)), 哪个用途 Positive Lookbehind :

    string[] subs = str.replaceAll("\[","").replaceAll("\]","").split("(?<=\)),");
    

    在simpe字符串函数中,可以删除 [ 和 ] 和使用 string.split("),") ,并返回 ) 在它之后。