使用正则表达式解析表格 - Java

7

我正在解析以下AWS成本实例表:

m1.small    1   1   1.7     1 x 160    $0.044 per Hour
m1.medium   1   2   3.75    1 x 410    $0.087 per Hour
m1.large    2   4   7.5     2 x 420    $0.175 per Hour
m1.xlarge   4   8   15      4 x 420    $0.35 per Hour

这是一个包含成本的文件:

input = new Scanner(file);
String[] values;
while (input.hasNextLine()) {
    String line = input.nextLine();
    values = line.split("\\s+"); // <-- not what I want...
    for (String v : values)
        System.out.println(v);
}

然而,这给我带来了:
m1.small
1
1
1.7
1
x
160
$0.044
per
Hour

这不是我想要的...经过修正的解析(使用正确的正则表达式)应该是这样的:

['m1.small', '1', '1', '1.7', '1 x 160', '$0.044', 'per Hour']

为了获得正确的结果,应该使用什么样的正则表达式?可以假设这个表格始终具有相同的模式。


4
实际数据是否使用制表符分隔?是否可能存在仅用一个空格分隔列的情况? - PurkkaKoodari
@Pietu1998 主要是...但不一定会产生更强大的正则表达式...这就是为什么我没有使用\\t+进行解析的原因。这些文件非常大,所以在搜索这些文件以修复缺少制表符可能是毫无意义的。 - cybertextron
你能使用 \\s{2,} 吗? - PM 77-1
怎么考虑反向操作?使用 \\s 进行分割,然后连接结果的部分。 - PM 77-1
@amow,你能把它变成一个答案吗? - cybertextron
显示剩余3条评论
3个回答

5

如果您想使用正则表达式,可以这样做:

        String s = "m1.small    1   1   1.7     1 x 160    $0.044 per Hour";
        String spaces = "\\s+";
        String type = "(.*?)";
        String intNumber = "(\\d+)";
        String doubleNumber = "([0-9.]+)";
        String dollarNumber = "([$0-9.]+)";
        String aXb = "(\\d+ x \\d+)";
        String rest = "(.*)";

        Pattern pattern = Pattern.compile(type + spaces + intNumber + spaces + intNumber + spaces + doubleNumber
                + spaces + aXb + spaces + dollarNumber + spaces + rest);
        Matcher matcher = pattern.matcher(s);
        while (matcher.find()) {
            String[] fields = new String[] { matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4),
                    matcher.group(5), matcher.group(6), matcher.group(7) };
            System.out.println(Arrays.toString(fields));
        }

请注意,我已将正则表达式分解为可读的形式。(作为一个长字符串,很难阅读/维护。)但是还有另一种方法。由于您知道哪些字段正在拆分,因此可以执行此简单的拆分并构建具有组合值的新数组:

        String[] allFields = s.split("\\s+");
        String[] result = new String[] { 
            allFields[0], 
            allFields[1],
            allFields[2],
            allFields[3],
            allFields[4] + " " + allFields[5] + " " + allFields[6],         
            allFields[7], 
            allFields[8] + " " + allFields[9] };
        System.out.println(Arrays.toString(result));

5
请尝试这个代码片段:https://regex101.com/r/sP6zW5/1。该代码能够匹配文本并生成列表。
如果你的文本模式一直相同,使用split可能过于复杂。可以考虑使用反向字符串格式化方法。注意保留HTML标记。

还有一件事... Java 抱怨 无效的转义序列 ... 我该如何解决? - cybertextron

4

按一个或多个空格分割。并且空格必须出现在以下上下文中。

DIGIT - SPACES - NOT "x"

NOT "x" - SPACES - DIGIT

    values = line.split("(?<=\\d)\\s+(?=[^x])|(?<=[^x])\\s+(?=\\d)")));

繁荣!非常感谢。 - cybertextron
@就差最后一点了...有些行有EBS Only $0.024,所以也应该匹配...在这种情况下,['EBS Only', '$0.024']..我试着添加了但没成功... - cybertextron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接