带制表符的java模式
我有一个文件,其中的行如下:带制表符的java模式,java,tabs,pattern-matching,Java,Tabs,Pattern Matching,我有一个文件,其中的行如下: string1 (tab) sting2 (tab) string3 (tab) string4 我想从每一行中得到,string3。。。现在,我从这些行了解到,string3位于第二个和第三个制表符之间。 有没有可能把它做成这样的图案 Pattern pat = Pattern.compile(".\t.\t.\t."); 听起来你只是想: foreach (String line in lines) { String[] bits = line.sp
string1 (tab) sting2 (tab) string3 (tab) string4
我想从每一行中得到,string3。。。现在,我从这些行了解到,string3位于第二个和第三个制表符之间。
有没有可能把它做成这样的图案
Pattern pat = Pattern.compile(".\t.\t.\t.");
听起来你只是想:
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类。这里可能没有必要,但值得注意
编辑:如注释中所述,如果要重复使用相同的模式,则编译单个模式并使用pattern.split更有效:
听起来你只是想:
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类。这里可能没有必要,但值得注意
编辑:如注释中所述,如果要重复使用相同的模式,则编译单个模式并使用pattern.split更有效:
如果您想要一个只捕获第三个字段而不捕获其他字段的正则表达式,可以使用以下命令:
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毫秒
明确的结论是,如果你打算反复使用它,它是,而不是依赖
基于此测试,编译的split与group regex的结果不是决定性的。也许正则表达式可以进一步调整以提高性能
更新
另一个简单的优化是重用匹配器,而不是在每个循环迭代中创建一个匹配器
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;
}
}
如果您想要一个只捕获第三个字段而不捕获其他字段的正则表达式,可以使用以下命令:
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毫秒
明确的结论是,如果你打算反复使用它,它是,而不是依赖
基于此测试,编译的split与group regex的结果不是决定性的。也许正则表达式可以进一步调整以提高性能
更新
另一个简单的优化是重用匹配器,而不是在每个循环迭代中创建一个匹配器
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;
}
}
代币器呢?您可以读取该行,然后使用标记器从选项卡中解析它。类似于StringTokenizer行=新StringTokenizermyString,\t;line.nextTokenizer呢?您可以读取该行,然后使用标记器从选项卡中解析它。类似于StringTokenizer行=新StringTokenizermyString,\t;line.nextToken您应该先看看Java内置库提供了什么,然后再自己进行lovel。Java的东西更加优化,可读性更强。在这种情况下,您至少有3或4个单行程序可以用来实现这一点。@AndreiBodnarescu:我以什么方式达到了如此低的级别?我和其他人一样使用了String.split,区别在于我明确地展示了如何处理多行,并且我验证了是否存在预期数量的部分,而不是盲目地使用第三个元素。显式验证允许出现比ArrayIndexOutOfBoundsException更有用的异常,例如,它可以包含行。出于兴趣,你有没有检查我的代码实际上在做什么,或者只是假设因为它不是一行代码,所以它是无用的?好吧,我觉得你有点联手对付我了。在我看来,问这个问题的人已经知道数组的大小以及当你访问数组外的索引时会发生什么,他也知道正则表达式以及它在Java中的工作方式,他唯一缺少的是String类上存在splitString正则表达式方法,所以我想简单地指出这一点就可以了。我还觉得,在“从不要求”中,我认为您添加的额外代码过于详细,无法断言某些东西。再说一次,这只是我的观点。@AndreiBodnarescu:两个独立行动的人不是真正的帮派,是吗?不,您还没有解释为什么您觉得我应该首先看看Java内置库在使用相同的met时提供了什么
霍德,你分裂了。你到底建议我去寻找什么,而我显然没有意识到?Java的哪一部分经过优化,可读性更好?你的第一条评论看起来好像你没有发现我已经在使用split了。如果你说你正确地阅读了我的答案,这是一个非常令人困惑的评论,我根本不理解。如果你多次执行拆分,例如在循环中逐行解析文件,然后,您应该创建一个模式,然后使用而不是。在您自己进行lovel之前,您应该先看看Java的内置库提供了什么。Java的东西更加优化,可读性更强。在这种情况下,您至少有3或4个单行程序可以用来实现这一点。@AndreiBodnarescu:我以什么方式达到了如此低的级别?我和其他人一样使用了String.split,区别在于我明确地展示了如何处理多行,并且我验证了是否存在预期数量的部分,而不是盲目地使用第三个元素。显式验证允许出现比ArrayIndexOutOfBoundsException更有用的异常,例如,它可以包含行。出于兴趣,你有没有检查我的代码实际上在做什么,或者只是假设因为它不是一行代码,所以它是无用的?好吧,我觉得你有点联手对付我了。在我看来,问这个问题的人已经知道数组的大小以及当你访问数组外的索引时会发生什么,他也知道正则表达式以及它在Java中的工作方式,他唯一缺少的是String类上存在splitString正则表达式方法,所以我想简单地指出这一点就可以了。我还觉得,在“从不要求”中,我认为您添加的额外代码过于详细,无法断言某些东西。再说一次,这只是我的观点。@AndreiBodnarescu:两个独立行动的人不是真正的帮派,是吗?不,你还没有解释为什么你觉得我应该首先看看Java的内置库提供了什么,当我使用和你一样的方法时。你到底建议我去寻找什么,而我显然没有意识到?Java的哪一部分经过优化,可读性更好?你的第一条评论看起来好像你没有发现我已经在使用split了。如果你说你正确地阅读了我的答案,这是一个非常令人困惑的评论,我根本不理解。如果你多次执行拆分,例如在循环中逐行解析文件,然后你应该创建一个模式,然后使用而不是。我强烈建议你显式地检查分割的结果,而不是盲目地假设至少有三个值。如果您确实希望正好有四个值,那么如果有四个以上的值,我可能仍然希望看到一个错误,如果少于三个,我肯定更喜欢一个明确的异常,包括有问题的行等信息,而不仅仅是ArrayIndexOutOfBoundsException。我知道这个潜在的异常,但如果他确定输入,他当然可以使用它。我强烈建议你明确检查拆分的结果,而不是而不是盲目地假设至少有三个值。如果您确实希望正好有四个值,那么如果有四个以上的值,我可能仍然希望看到一个错误,如果少于三个,我肯定更喜欢一个明确的例外,包括有问题的行等信息,而不仅仅是ArrayIndexOutOfBoundsException。我知道这个潜在的例外,但如果他确定输入,他当然可以使用它。