当前位置: 首页 > 面试题库 >

如何使用Java的Scanner类和正则表达式标记输入?

裴劲
2023-03-14
问题内容

出于我自己的目的,我试图在Java中构建一个标记器,在其中可以定义常规语法,并根据该标记对输入进行标记。不建议使用StringTokenizer类,并且我在Scanner中发现了几个函数,这些函数可以提示我要执行的操作,但还没有运气。有人知道解决这个问题的好方法吗?


问题答案:

“扫描程序”的名称有点误导,因为该词通常用于表示词法分析器,而这并不是Scanner的意思。所有这些都可以替代scanf()您在C,Perl 等人中
找到的功能。像StringTokenizer和一样split(),它被设计为向前扫描,直到找到与给定模式的匹配为止,然后跳过的任何内容都将作为令牌返回。

另一方面,词法分析器必须检查和分类每个字符,即使只是为了确定是否可以安全地忽略它们也是如此。这意味着,在每次匹配之后,它可能会应用多种模式,直到找到
从该点开始 匹配的模式。否则,它可能会发现序列“ //”,并认为它已找到注释的开始,这时它确实位于字符串文字中,而只是没有注意到开头的引号。

当然,它实际上要比这复杂得多,但是我只是在说明为什么诸如StringTokenizer
split()和Scanner之类的内置工具不适合此类任务。但是,可以将Java的regex类用于有限形式的词法分析。实际上,由于添加了新的Matcher
API来支持Scanner类(即区域和usePattern()方法),因此添加了Scanner类变得更加容易。这是在Java的regex类之上构建的基本扫描器的示例。

import java.util.*;
import java.util.regex.*;

public class RETokenizer
{
  static List<Token> tokenize(String source, List<Rule> rules)
  {
    List<Token> tokens = new ArrayList<Token>();
    int pos = 0;
    final int end = source.length();
    Matcher m = Pattern.compile("dummy").matcher(source);
    m.useTransparentBounds(true).useAnchoringBounds(false);
    while (pos < end)
    {
      m.region(pos, end);
      for (Rule r : rules)
      {
        if (m.usePattern(r.pattern).lookingAt())
        {
          tokens.add(new Token(r.name, m.start(), m.end()));
          pos = m.end();
          break;
        }
      }
      pos++;  // bump-along, in case no rule matched
    }
    return tokens;
  }

  static class Rule
  {
    final String name;
    final Pattern pattern;

    Rule(String name, String regex)
    {
      this.name = name;
      pattern = Pattern.compile(regex);
    }
  }

  static class Token
  {
    final String name;
    final int startPos;
    final int endPos;

    Token(String name, int startPos, int endPos)
    {
      this.name = name;
      this.startPos = startPos;
      this.endPos = endPos;
    }

    @Override
    public String toString()
    {
      return String.format("Token [%2d, %2d, %s]", startPos, endPos, name);
    }
  }

  public static void main(String[] args) throws Exception
  {
    List<Rule> rules = new ArrayList<Rule>();
    rules.add(new Rule("WORD", "[A-Za-z]+"));
    rules.add(new Rule("QUOTED", "\"[^\"]*+\""));
    rules.add(new Rule("COMMENT", "//.*"));
    rules.add(new Rule("WHITESPACE", "\\s+"));

    String str = "foo //in \"comment\"\nbar \"no //comment\" end";
    List<Token> result = RETokenizer.tokenize(str, rules);
    for (Token t : result)
    {
      System.out.println(t);
    }
  }
}

顺便说一句,这是我所发现的唯一对lookingAt()方法有用的方法。:D



 类似资料:
  • 我有一根绳子,看起来像这样:

  • 我想验证输入的代码是否是HTML代码(必须以<代码> 我试着这么做 但是我有一个问题需要在代码中做一个\n,我需要验证第一个和结束标签(=

  • 问题内容: 首先,我阅读以下文档 http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html 而且我想找到除@’之外的任何标点符号,但我不太了解。 这是 : 结果是没有匹配。 是否有任何不匹配? 谢谢 MRizq 问题答案: 您要匹配两个字符,而不是一个。使用(负)前瞻应解决以下任务:

  • 本文向大家介绍Java正则表达式使用,包括了Java正则表达式使用的使用技巧和注意事项,需要的朋友参考一下 一:抓取网页中的Email地址 利用正则表达式匹配网页中的文本 将网页内容分割提取 打印结果: 867124664@qq.com 260678675@QQ.com 806208721@qq.com hr_1985@163.com 32575987@qq.com qingchen0501@12

  • 问题内容: 原始数据是: 我想匹配一条线,但是不能使用 但是,我可以使用match 。 我该如何搭配 问题答案: 默认情况下,和分别匹配输入的开始和结束。您需要使用启用多行模式,这会导致并匹配行的开始和结束: 演示: 产生以下输出: 编辑我 没有任何匹配的事实是因为默认情况下,和不匹配。如果您通过启用了DOT-ALL ,也使匹配了它们,那么您将看到整个输入字符串都被匹配了: 编辑二 在这种情况下,

  • 我希望有一个通用的框架来编写一些正则表达式中的语法验证规则,这样我就可以在前端和后端都使用它们。我使用javascript作为前端,使用java作为后端。我想在前端做一个表单提交,但是在提交表单之前,我需要执行一些语法规则检查。当请求到达后端时,我希望评估相同的规则集。 我想把这些规则放在一个可以加载javascript和java代码的公共位置,这样我只需要更改这个公共位置的规则,它们就会反映到两