新编辑**
我试图解析一个名为stuff.make的文件中包含的以下行。
[Utilize 1x Bolt to Helicopter until 10s]
[Utilize Boat until 5s]
[Utilize 7x Bolt to Helicopter until 2s]
[Utilize 4x Wrench to Tank until 3s]
编辑**想要输出(我的目标是输出):
1
Bolt
Helicopter
10
Boat
5
7
Bolt
Helicopter
2
4
Wrench
Tank
3
答案 0 :(得分:1)
在第一个正则表达式中,您错过了\s
Silver:
在第二个正则表达式中,您错过了x
(\\d*)
Pattern p1 = Pattern.compile("\\[(Silver):\\s(\\d+)\\]");
Pattern p2 = Pattern.compile("\\[Utilize (\\d*)x (\\w*)");
// I used * so that in the case of line 3, where a word comes after 'Utilize'
// rather than number, * doesn't have to match so would ignore \\d* and only
// take into account the \\w* to print out 'Boat'
Matcher m1 = p1.matcher(list[i]);
Matcher m2 = p2.matcher(list[i]);
while(m1.find()){
System.out.println(m1.group(1));// Prints out Silver
System.out.println(m1.group(2));// Prints out 9
}
while(m2.find()){
System.out.println(m2.group(1)); //Should print 2 then in next line be ignored
System.out.println(m2.group(2)); //Should print Bolt then next line Boat
}
修改强>
您添加?
的新正则表达式仅适用于前一个字符。因此,为了使其正常工作,您需要将to
组合在一起以使整个单词可选。为了简化你的正则表达式,我将\s
扔进了小组。
Pattern p3 = Pattern.compile("(?:to\\s)?(\\w*)\\suntil\\s(\\d+)s\\]");
修改强>
在评论中,我被问到为什么我使用\s
而不是空格。我认为在答案中我会更容易解释。简单地说,我更喜欢使用\s
,除非我有理由不这样做。 \s
匹配任何空格字符,这使得空格,制表符或其他空格字符与正则表达式匹配。有了这个,意识到\s
会使你的Regex稍微灵活一点,但代价是不知道匹配的确切字符。另请注意,不同的正则表达式引擎可以不同地实现\s
,这就是为什么我说“其他空白字符”的原因。早。
那么什么时候你会在\s
语法上使用空格?
如果除了空格之外还有其他任何字符,那么您不希望正则表达式匹配。这在某些情况下可能有效,但它确实取决于正则表达式的要求。也许它是一段重要的代码,你不想触摸任何符合你期望的东西。
所有这一切并不是说你不能选择超过\s
的空格。只要了解其中的差异,就可以明智地选择。
此处\s
字符为short tutorial。
修改强>
Scanner类无法按照您在while循环中尝试使用它的方式使用。以下是您需要重新组织该部分的方法
while (scan.hasNextLine()) {
s = scan.nextLine();
}
请注意,在阅读该行之前,请确保其他线路可用。
修改强>
这是我的测试程序,输入文件和输出。我已修改此内容以匹配您已修改问题的输出。这里的主要变化是我修改了代码只需要一个Regex。你可以用两个来完成这个,但是知道你想要完成什么我认为这是一种更清洁的方式来使用它。正则表达式仍然非常简单。它只是你们两者之间的合并,我让一些捕获组可选来处理不同的文本。
我做的其他事情是清理代码并修复你的错误。请花点时间查看更改并了解它们。主要的是我重新组织了try/catch
块并添加了finally
块。因此,您可以坐下来阅读有关正确资源处理和尝试捕获的信息。
下面的链接将显示正则表达式,它会为您提供一切的详细信息。应该有助于你理解我写的正则表达式。
public static void main(String[] args) throws IOException {
Parser("C:\\Users\\Nathan.DOZIERINC\\Downloads\\test.txt");
}
public static void Parser(String Path) //Got the path of stuff.make
{
File f = new File(Path);
Scanner scan = null;
//Notice I combined the two try/catches you had and included a finally. The way you were
//doing this would have caused issues when the file was not found. So please read up on using try/catch/finally.
try {
scan = new Scanner(f);
while (scan.hasNextLine()) {
String s = scan.nextLine();
Pattern p1 = Pattern.compile("(?:(?<count>\\d+)x)?\\s(?<type>[\\w]+)(?:\\sto\\s(?<secondType>\\w+))?\\suntil\\s(?<seconds>\\d+)s\\]");
Matcher m1 = p1.matcher(s);
while (m1.find()) {
String count = m1.group("count");
String type = m1.group("type");
String secondType = m1.group("secondType");
String seconds = m1.group("seconds");
//If count is null, that means the regex didn't find this OPTIONAL group
if (count != null)
System.out.println(count);
//I'm not checking for null on type simply because the regex will fail
// if this group is not found.
System.out.println(type);
//If secondType is null, that means the regex didn't find this OPTIONAL group
if (secondType != null)
System.out.println(secondType);
//I'm not checking for null on type simply because the regex will fail
// if this group is not found.
System.out.println(seconds);
System.out.println("---");
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
//Here it prints out the error: Error while reading file line by line: For input string: ""
System.out.println("Error while reading file line by line: " + e.getMessage());
} finally {
//ALWAYS clean up your resources, you were not doing this in the original
if (scan != null) {
scan.close();
}
}
}
test.txt的内容
[Utilize 1x Bolt to Helicopter until 10s]
[Utilize Boat until 5s]
[Utilize 7x Bolt to Helicopter until 2s]
[Utilize 4x Wrench to Tank until 3s]
输出我接收
1
Bolt
Helicopter
10
---
Boat
5
---
7
Bolt
Helicopter
2
---
4
Wrench
Tank
3
---