【问题标题】:Scanner hasNext() method and escape characters扫描仪 hasNext() 方法和转义字符
【发布时间】:2017-01-30 17:32:43
【问题描述】:

我正在尝试确定Scanner 中的下一个标记是否包含某个字符串。但是,如果令牌中有 \n 或 \r,则 hasNext(String) 方法无论如何都会返回 false。 (我正在使用 Eclipse。)

默认分隔符(空格)不会出现此问题。但是如果使用 useDelimiter() - 甚至将分隔符设置为 " " - 那么 hasNext(String) 总是返回 false。

如果令牌中某处有转义字符并且分隔符也被重置,ScannerhasNext(String) 方法是否总是返回 false?

import java.util.*;

public class ScannerDemo {

    public static void main(String[] args) {

        Scanner scanner = new Scanner("abcdefg\n\rX");
        scanner.useDelimiter("X");

        // Returns false!! Why?
        System.out.println("" + scanner.hasNext(".*c.*"));
        System.out.println(scanner.next());
        System.out.println("-------------------------------");

        scanner.close();

        scanner = new Scanner("abcde\n\rXfg");
        scanner.useDelimiter("X");

        // Returns false!! Why?
        System.out.println("" + scanner.hasNext(".*c.*"));
        System.out.println(scanner.next());
        System.out.println("-------------------------------");

        scanner.close();

        scanner = new Scanner("\n\rabcdeXfg");
        scanner.useDelimiter("X");

        // Returns false!! Why?
        System.out.println("" + scanner.hasNext(".*c.*"));
        System.out.println(scanner.next());
        System.out.println("-------------------------------");

        scanner.close();

        scanner = new Scanner("abcdeXfg\n\r");
        scanner.useDelimiter("X");

        // Returns true, as expected
        System.out.println("" + scanner.hasNext(".*c.*"));
        System.out.println(scanner.next());
        System.out.println("-------------------------------");

        scanner.close();

        scanner = new Scanner("abcdeXfg");
        scanner.useDelimiter("X");

        // Returns true, as expected
        System.out.println("" + scanner.hasNext(".*c.*"));
        System.out.println(scanner.next());
        System.out.println("-------------------------------");

        scanner.close();

    }
}

【问题讨论】:

    标签: java regex java.util.scanner


    【解决方案1】:

    . 正则表达式通配符默认不匹配 \r\n

    您需要指定标志DOTALL,但由于您没有直接使用Pattern 类,因此请在您的正则表达式中添加(?s)

    scanner.hasNext("(?s).*c.*")
    

    正如DOTALL javadoc 所说:

    在 dotall 模式下,表达式 . 匹配任何字符,包括行终止符。默认情况下,此表达式不匹配行终止符。

    Pattern 的 javadoc 中对 . 的描述也涵盖了这一点:

    .      任何字符(可能匹配也可能不匹配 line terminators

    链接说:

    正则表达式. 匹配除行终止符以外的任何字符,除非指定了DOTALL 标志。

    【讨论】:

    • 在正则表达式中添加 '(?s)' 确实可以解决问题。我仍然不明白为什么 \r\n 会导致问题 - 这些不是我要匹配的字符。而且我不确定为什么“useDelimiter()”会影响问题。
    • @MaeWarren 当你指定useDelimiter("X")时,第一个token是abcdefg\n\r,所以当你调用hasNext(".*c.*")时,第一个.*匹配abc匹配@987654344 @,但第二个.* 不匹配defg\n\r除非 . 可以匹配行终止符。
    • 我明白了。我相信这完全回答了这个问题。谢谢。
    【解决方案2】:

    您可能需要查看here。那里的答案之一解释说:

    “如果您有一堆带有 .next() 的手表,那么您的 IDE ......实际上每一个都在推进光标位置。” --Amalgovinus

    这可能是您遇到的问题。

    【讨论】:

    • 不是这样的。仅当其中包含转义字符时才会出现此问题。并且问题发生在第一个 .next() 执行之前。
    • 嗯。我现在手头没有 IDE(我在手机上),而且我不记得遇到过这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 2017-05-26
    • 2017-06-06
    相关资源
    最近更新 更多