【问题标题】:How to make Scanner return delimiters as tokens如何使扫描仪返回分隔符作为标记
【发布时间】:2020-02-25 15:52:46
【问题描述】:

我正在尝试使用java.util.Scanner 来标记算术表达式,其中分隔符可以是:

  • 空白(\s+\p{Space}+),应丢弃
  • 标点符号 (\p{Punct}),应作为标记返回

示例

给定这个表达式:

12 + (ab-bc*3)

我希望 Scanner 返回这些令牌:

  • 12
  • +
  • (
  • ab
  • -
  • bc
  • *
  • 3
  • )

代码

到目前为止,我只能:

  • 吃掉所有的标点符号(不是我想要的):
    • new Scanner("12 + (ab-bc*3)").useDelimiter("\\p{Space}+|\\p{Punct}").tokens().collect(Collectors.toList())
    • 结果:"12", "", "", "", "ab", "bc", "3"
  • 使用positive lookahead 取得部分成功
    • new Scanner("12 + (ab-bc*3)").useDelimiter("\\p{Space}+|(?=\\p{Punct})").tokens().collect(Collectors.toList())
    • 结果:"12", "+", "(ab", "-bc", "*3", ")"

但现在我被困住了。

【问题讨论】:

  • 你可以使用"\\p{Punct}|\\w+"正则表达式匹配它们
  • 不幸的是,这个正则表达式吃掉了我所有的令牌:new Scanner("12 + (ab-bc*3)").useDelimiter("\\p{Punct}|\\w+").tokens() 只返回空字符串
  • 我说匹配它们,在扫描仪中,你用模式分割。见Java demo
  • 我会说你不会得到你想要的,因为你试图只指定你想要的分隔符类型,但你从来没有说你想要什么样的标记。就扫描仪而言,"-bc" 中没有分隔符,我认为没有任何可能的配置可以改变它(从技术上讲,其中的分隔符是一个“空字符”,这实际上不是一个东西)。你需要说出你想要什么样的令牌,通过使用适当的正则表达式将 .token() 更改为 .findAll,就像 Wiktor 建议的那样。
  • @DaniloPiazzalunga,您可能希望将模式保存在实际应用中的某个位置,而不是继续为同一事物创建和解析正则表达式。

标签: java regex java.util.scanner delimiter


【解决方案1】:

匹配 方法允许您在此处使用更简单的正则表达式:

String text = "12 + (ab-bc*3)";
List<String> results = Pattern.compile("\\p{Punct}|\\w+").matcher(text)
    .results()
    .map(MatchResult::group)
    .collect(Collectors.toList());
System.out.println(results); 
// => "12", "+", "(", "ab", "-", "bc", "*", "3", ")"

Java demo

正则表达式匹配

  • \p{Punct} - 标点和符号字符
  • | - 或
  • \w+ - 1+ 个字母、数字或 _ 字符。

请参阅regex demo(为了演示目的已转换为 PCRE)。

【讨论】:

    猜你喜欢
    • 2011-01-23
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多