Java正则表达式和模式匹配:如何在不包含“空格”的模式中找到它们?

5

所以,我需要为作业编写一个编译器扫描器,并认为使用正则表达式会很“优雅”。事实是,我之前很少使用它们,而且已经很久了。所以我忘记了大部分关于它们的东西,需要四处看看。我已经成功地将它们用于标识符(或者至少我认为是这样,我仍然需要进行一些进一步的测试,但现在它们看起来都还不错),但是我在数字识别方面遇到了问题。

函数nextCh()读取输入上的下一个字符(向前看字符)。我想在这里做的是检查这个字符是否匹配正则表达式[0-9]*。我将每个匹配的字符附加到当前标记的str字段中,然后读取此字段的int值。它可以识别单个数字输入,例如“123”,但我遇到的问题是对于输入“123 456”,最终的str将是“123 456”,而我应该得到两个具有字段“123”和“456”的单独标记。为什么会匹配“ ”?

private void readNumber(Token t) {
    t.str = "" + ch; // force conversion char --> String
    final Pattern pattern = Pattern.compile("[0-9]*");
    nextCh(); // get next char and check if it is a digit
    Matcher match = pattern.matcher("" + ch);
    while (match.find() && ch != EOF) {
        t.str += ch;
        nextCh();
        match = pattern.matcher("" + ch);
    }
    t.kind = Kind.number;
    try {
        int value = Integer.parseInt(t.str);            
        t.val = value;          
    } catch(NumberFormatException e) {
        error(t, Message.BIG_NUM, t.str);           
    }

谢谢!

PS:我使用以下代码解决了我的问题。然而,我想理解我的正则表达式中的缺陷在哪里。

    t.str = "" + ch;
    nextCh(); // get next char and check if it is a number
    while (ch>='0' && ch<='9') {
        t.str += ch;
        nextCh();
    }
    t.kind = Kind.number;
    try {
        int value = Integer.parseInt(t.str);            
        t.val = value;          
    } catch(NumberFormatException e) {
        error(t, Message.BIG_NUM, t.str);           
    }

编辑:事实证明,我的正则表达式也无法识别标识符(仍然包括空格),所以我不得不转而使用类似于我的“解决方案”的系统(带有许多条件)。看来我需要重新学习正则表达式:O

3个回答

2

我不确定这是否与您的情况相关,但是这个:

Pattern.compile("[0-9]*");

由于星号的存在,它可以匹配字符串中零个或更多数字。我认为空格被匹配是因为它也符合“零个数字”的条件。如果你想要确保字符是数字,你需要使用加号来匹配一个或多个数字:

Pattern.compile("[0-9]+");

或者,如果您只是逐个比较单个字符,则只需匹配一个数字:

Pattern.compile("^[0-9]$");

我尝试了第三种方法。不幸的是,即使使用您提供的两个额外的可能性,我也无法检测到“123”数字...我可能需要重新检查代码。另一个问题:您能告诉我^符号的作用吗?我无法真正理解我前几天找到的例子... - PLB
^表示字符串将从开头匹配。$表示从结尾匹配。因此,如果你在正则表达式两侧使用^$,就意味着该字符串必须完全匹配。如果没有它们,像' rdpa5'这样的字符串会与'5'一样匹配,因为有一个数字出现在字符串中某个地方。当然,如果你只是每次比较单个字符,我认为这些语句结构不会有太大区别。 - David John Welsh
顺便说一下,如果完全不匹配了,可能是因为您包含了斜杠。如果您使用构造函数构造RegExp,则不需要它们。我会更新答案... - David John Welsh
这不太对。OP使用的模式是正确的,但是Matcher方法是错误的。请看我的答案。 - Ian McLaird
哦,太酷了!Stack Overflow的好处就是即使你自己没有提问,也能学到东西:-D - David John Welsh

1

您应该使用matches方法而不是find方法。根据文档:

matches方法尝试将整个输入序列与模式匹配

find方法扫描输入序列,寻找与模式匹配的下一个子序列。

换句话说,如果使用find,如果字符串包含任何数字,您都会得到匹配,但如果使用matches,则整个字符串必须匹配模式。

例如,请尝试以下内容:

Pattern p = Pattern.compile("[0-9]*");
Matcher m123abc = p.matcher("123 abc");
System.out.println(m123abc.matches());  // prints false
System.out.println(m123abc.find());     // prints true

0

使用一个更简单的正则表达式,例如

/\d+/

在哪里

  • \d 表示数字
  • + 表示一个或多个

在代码中:

final Pattern pattern = Pattern.compile("\\d+");

可能已经太晚了(凌晨3:30),我还在写Java。我尝试使用您的正则表达式,但Eclipse告诉我\d是无效的转义序列... - PLB
感谢编辑。不幸的是,它找不到任何数字(我明天会进行调试以查看它的确切操作)...这很奇怪。 - PLB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接