Java 扫描仪、模式以及useDelimiter() 和skip() 之间的区别
Java Scanner, Pattern and difference between useDelimiter() and skip()
java.util.Scanner.useDelimiter()
和 Scanner.skip()
和有什么不一样?例如,我将这些字符串格式化为如下所示:
String line1 = "0---20.000:\t\t \t12%";
String line2 = "0--20.000:\t 12%";
String line3 = "0-20.000: \t \t12%";
String error = "0-: \t\t12%";
我需要这个输出:
0
20.000
12
我应该使用扫描仪和对所有三个字符串都有效的模式,我需要控制标记为三个,否则会抛出异常。
我可以用两种 Scanner 方法得到这个输出吗?
我应该使用哪种正则表达式模式?
其他号码也必须有效。
编辑:这是我的尝试:
package scanners;
import java.util.Scanner;
public class ScannerTry {
public static void main(String[] args) {
String line = "0--20.000: 12%";
Scanner scan = new Scanner(line);
scan.useDelimiter("[-*:*\t*%]*");
while (scan.hasNext()){
System.out.println(scan.next());
}
scan.close();
}
}
但是输出是:
0
2
0
.
0
0
0
1
2
这是您指定的分隔符:
scan.useDelimiter("[-*:*\t*%]*");
方括号包含字符列表,使用它们表示"match a character that is in this list"。 *
外方括号表示"match 0 or more occurrences of one of these characters."
您一次获得一个字符的原因是当您匹配 0 次或多次出现时,这意味着空字符串(长度为 0 的字符串)与分隔符模式匹配。由于输入文件中每 2 个字符之间有一个空字符串(它们之间没有字符,因此空字符串匹配),扫描器会将每个字符视为它自己的标记。因此,您要做的第一件事就是将最后一个 *
更改为 +
,这意味着 "match 1 or more occurrences"。现在空字符串将不匹配。
你的模式的第二个问题是方括号内的 *
只是意味着星号是你匹配的字符之一; “0 或更多”的含义不适用于方括号内。事实上,只要你有方括号,无论里面是什么,这个模式 总是恰好匹配一个字符 。因此,任何 *
、+
或您要指定为重复的任何其他内容都需要放在方括号之外。
如果你只取出*
:
scan.useDelimiter("[-:\t%]+");
现在这将匹配任何序列的 -
、:
、制表符和 %
字符。不过,它不会匹配 space,而且我在您的某些示例中看到了 space。所以你可能想在方括号内添加一个 space 。或者你可以这样说:
scan.useDelimiter("[-:\s%]+");
因为方括号内的 \s
组合表示匹配 "any whitespace character",其中包括 space、制表符和其他一些如换行符。 (但只有在您确实想要匹配换行符时才这样做。)
另一件事:您将 -
放在方括号内的第一个位置是正确的。如果你不这样做,它可能有不同的含义:
"[a-z]"
匹配从 a
到 z
的任何字符,但不匹配连字符。然而:
"[a\-z]"
匹配 a
、z
或连字符。一些程序员(包括我),当我们想要在字符集中使用连字符时,即使没有必要,也会在连字符上使用这个反斜杠,以避免任何可能的混淆:
scan.useDelimiter("[\-:\t%]+");
java.util.Scanner.useDelimiter()
和 Scanner.skip()
和有什么不一样?例如,我将这些字符串格式化为如下所示:
String line1 = "0---20.000:\t\t \t12%";
String line2 = "0--20.000:\t 12%";
String line3 = "0-20.000: \t \t12%";
String error = "0-: \t\t12%";
我需要这个输出:
0
20.000
12
我应该使用扫描仪和对所有三个字符串都有效的模式,我需要控制标记为三个,否则会抛出异常。
我可以用两种 Scanner 方法得到这个输出吗?
我应该使用哪种正则表达式模式?
其他号码也必须有效。
编辑:这是我的尝试:
package scanners;
import java.util.Scanner;
public class ScannerTry {
public static void main(String[] args) {
String line = "0--20.000: 12%";
Scanner scan = new Scanner(line);
scan.useDelimiter("[-*:*\t*%]*");
while (scan.hasNext()){
System.out.println(scan.next());
}
scan.close();
}
}
但是输出是:
0
2
0
.
0
0
0
1
2
这是您指定的分隔符:
scan.useDelimiter("[-*:*\t*%]*");
方括号包含字符列表,使用它们表示"match a character that is in this list"。 *
外方括号表示"match 0 or more occurrences of one of these characters."
您一次获得一个字符的原因是当您匹配 0 次或多次出现时,这意味着空字符串(长度为 0 的字符串)与分隔符模式匹配。由于输入文件中每 2 个字符之间有一个空字符串(它们之间没有字符,因此空字符串匹配),扫描器会将每个字符视为它自己的标记。因此,您要做的第一件事就是将最后一个 *
更改为 +
,这意味着 "match 1 or more occurrences"。现在空字符串将不匹配。
你的模式的第二个问题是方括号内的 *
只是意味着星号是你匹配的字符之一; “0 或更多”的含义不适用于方括号内。事实上,只要你有方括号,无论里面是什么,这个模式 总是恰好匹配一个字符 。因此,任何 *
、+
或您要指定为重复的任何其他内容都需要放在方括号之外。
如果你只取出*
:
scan.useDelimiter("[-:\t%]+");
现在这将匹配任何序列的 -
、:
、制表符和 %
字符。不过,它不会匹配 space,而且我在您的某些示例中看到了 space。所以你可能想在方括号内添加一个 space 。或者你可以这样说:
scan.useDelimiter("[-:\s%]+");
因为方括号内的 \s
组合表示匹配 "any whitespace character",其中包括 space、制表符和其他一些如换行符。 (但只有在您确实想要匹配换行符时才这样做。)
另一件事:您将 -
放在方括号内的第一个位置是正确的。如果你不这样做,它可能有不同的含义:
"[a-z]"
匹配从 a
到 z
的任何字符,但不匹配连字符。然而:
"[a\-z]"
匹配 a
、z
或连字符。一些程序员(包括我),当我们想要在字符集中使用连字符时,即使没有必要,也会在连字符上使用这个反斜杠,以避免任何可能的混淆:
scan.useDelimiter("[\-:\t%]+");