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]"

匹配从 az 的任何字符,但不匹配连字符。然而:

"[a\-z]"

匹配 az 或连字符。一些程序员(包括我),当我们想要在字符集中使用连字符时,即使没有必要,也会在连字符上使用这个反斜杠,以避免任何可能的混淆:

scan.useDelimiter("[\-:\t%]+");