繁体   English   中英

带制表符的Java模式

[英]java pattern with tab characters

我有一个像这样的文件:

string1 (tab) sting2 (tab) string3 (tab) string4

我想从每一行中获取string3 ...现在从行中获取的所有信息是string3在第二个和第三个制表符之间。 是否可以采用类似的模式

Pattern pat = Pattern.compile(".\t.\t.\t.");
String string3 = tempValue.split("\\t")[2];

听起来您只想要:

foreach (String line in lines) {
    String[] bits = line.split("\t");
    if (bits.length != 4) {
        // Handle appropriately, probably throwing an exception
        // or at least logging and then ignoring the line (using a continue
        // statement)
    }
    String third = bits[2];
    // Use...
}

(您可以转义字符串,以便正则表达式引擎必须将反斜杠-t解析为制表符,但不必这样做。上面的方法很好用。)

使用正则表达式的内置String.split方法的另一种替代方法是Guava Splitter类。 在这里可能没有必要,但是值得注意。

编辑:如注释中所述,如果您要重复使用相同的模式,则编译单个Pattern并使用Pattern.split更有效:

private static final Pattern TAB_SPLITTER = Pattern.compile("\t");

...

String[] bits = TAB_SPLITTER.split(line);

如果要使用仅捕获第三个字段而没有其他内容的正则表达式,则可以使用以下命令:

String regex = "(?:[^\\t]*)\\t(?:[^\\t]*)\\t([^\\t]*)\\t(?:[^\\t]*)";
Pattern pattern = Pattern.compile(regex);

Matcher matcher = pattern.matcher(input);
if (matcher.matches()) {
  System.err.println(matcher.group(1));
}

我不知道 这对于解析大文件是否比split("\\\\t")更好。

更新

我很想知道简单拆分和更明确的正则表达式如何执行,所以我测试了三种不同的解析器实现。

/** Simple split parser */
static class SplitParser implements Parser {
    public String parse(String line) {
        String[] fields = line.split("\\t");
        if (fields.length == 4) {
            return fields[2];
        }
        return null;
    }
}

/** Split parser, but with compiled pattern */
static class CompiledSplitParser implements Parser {
    private static final String regex = "\\t";
    private static final Pattern pattern = Pattern.compile(regex);

    public String parse(String line) {
        String[] fields = pattern.split(line);
        if (fields.length == 4) {
            return fields[2];
        }
        return null;
    }
}

/** Regex group parser */
static class RegexParser implements Parser {
    private static final String regex = "(?:[^\\t]*)\\t(?:[^\\t]*)\\t([^\\t]*)\\t(?:[^\\t]*)";
    private static final Pattern pattern = Pattern.compile(regex);

    public String parse(String line) {
        Matcher m = pattern.matcher(line);
        if (m.matches()) {
            return m.group(1);
        }
        return null;
    }
}

我针对相同的百万行文件运行了十次。 这是平均结果:

  • 分割:2768.8毫秒
  • 编译后的分割时间:1041.5毫秒
  • 组正则表达式:1015.5毫秒

明确的结论是,如果要重复使用模式 ,则编译模式而不是依赖String.split 非常重要

基于此测试,编译后的拆分与组正则表达式的结果不是结论性的。 正则表达式可能会进一步调整性能。

更新

进一步的简单优化是重用Matcher,而不是在每个循环迭代中创建一个Matcher。

static class RegexParser implements Parser {
    private static final String regex = "(?:[^\\t]*)\\t(?:[^\\t]*)\\t([^\\t]*)\\t(?:[^\\t]*)";
    private static final Pattern pattern = Pattern.compile(regex);

    // Matcher is not thread-safe...
    private Matcher matcher = pattern.matcher("");

    // ... so this method is no-longer thread-safe
    public String parse(String line) {
        matcher = matcher.reset(line);
        if (matcher.matches()) {
            return matcher.group(1);
        }
        return null;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM