【问题标题】:Returning java regex (words, spaces, special characters, double quotes)返回 java 正则表达式(单词、空格、特殊字符、双引号)
【发布时间】:2013-09-05 04:25:02
【问题描述】:

我正在尝试使用 java 正则表达式来标记任何语言源文件。我希望列表返回的是:

  • 话 ([a-z_A-Z0-9])
  • 空格
  • [()*.,+-/=&:] 中的任何一个作为单个字符
  • 和引号中的项目。

这是我目前的代码:

Pattern pattern = Pattern.compile("[\"(\\w)\"]+|[\\s\\(\\)\\*\\+\\.,-/=&:]");

Matcher matcher = pattern.matcher(str);
List<String> matchlist = new ArrayList<String>();

while(matcher.find()) {
    matchlist.add(matcher.group(0));
}

例如,

"I" am_the 2nd "best".

返回:列表,大小 8

("I", ,am_the, ,2nd, ,"best", .)

这就是我想要的。但是,如果整个句子都被引用,除了句号:

"I am_the 2nd best".

返回:列表,大小 8

("I, ,am_the, ,2nd, ,best", .)

我希望它能够返回:列表,大小 2

("I am_the 2nd best", .)

如果这有意义的话。我相信它适用于我想要的一切,除了返回字符串文字(我想保留引号)。我从允许我实现这一目标的模式中遗漏了什么?

无论如何,如果有一个我看不到的更容易使用的模式,请帮助我。上面显示的模式是许多试验/错误的编译。非常感谢您的任何帮助。

【问题讨论】:

  • 这看起来有点棘手,可能是您的要求不兼容。什么时候应该引用 1 对和引用 4 而不是引用 2?
  • 您不能将具有相同字符的构造嵌套用于开始和结束并期望解析器理解其含义。这是模棱两可的。使用不同的字符开始和结束它可以工作,但是,您不能使用单个正则表达式评估来解析嵌套结构。
  • 好吧,也许第二个有点不必要,我很抱歉将这个例子放在一起,但我可以使用类似的正则表达式来捕捉外部引号,例如“嗨,那里”。作为一个返回值,但要不然就给我我的所有作品,如第一个示例所示?我当前的代码仍会返回“嗨,那里”。作为一块而不是一个对象。
  • StreamTokenizer 可以识别带引号的字符串。
  • 添加了“文本解析”和“词法分析器”标签。

标签: java regex text-parsing lexer


【解决方案1】:

首先,您需要将单词匹配代码与字符串文字匹配代码分开。对于单词匹配,使用:

\w+

接下来是空格。

\s+

要将字符串作为一个标记进行匹配,您需要允许更多字符,而不仅仅是\w。那只允许字母数字字符和_,这意味着不允许空格和符号。您还需要将开始和结束的引号移到方括号之外。

并且不要忘记使用反斜杠来转义字符。您希望在字符串中允许 \"

"(\\.|[^"])+"

最后是符号。您可以列出所有符号,或者您可以将任何非单词、非空白、非引号字符视为符号。我推荐后者,这样您就不会被 @| 等其他符号呛到。所以对于符号:

[^\s\w"]

将这些部分放在一起,我们得到了这个组合的正则表达式:

\w+|\s+|"(\\.|[^"])+"|[^\s\w"]

或者,正确地转义所有内容,以便将其放入源代码中:

Pattern pattern = Pattern.compile("\\w+|\\s+|\"(\\\\.|[^\"])+\"|[^\\s\\w\"]");

【讨论】:

  • 非常感谢您的解释。我总是觉得有趣的是,在您阅读了问题的确切答案之后,会有这种“哦,哇,这很有意义”的时刻。 :) 我相信这正是我所需要的。
【解决方案2】:

通常,在解析文本时,您所描述的过程称为“词法分析”,使用的函数称为“词法分析器”,用于将输入流分解为可识别的标记,如单词、数字、空格、期间等。

词法分析器的输出由“解析器”使用,该解析器通过识别属于一起的标记组来进行“句法分析”,例如 [双引号] [单词] [双引号]。

我建议您遵循相同的两遍策略,因为它已在许多解析器中一次又一次地得到证明。

所以,你的第一步可能是使用这个正则表达式作为你的词法分析器:

\W|\w+

这会将您的输入文本分解为单个非单词字符(如空格、双引号和单引号、逗号、句点等)或一个或多个单词字符的序列,其中\w 实际上只是一种快捷方式为[a-zA-Z_0-9]

因此,使用上面的示例:

String str=/"I" am_the 2nd "best"./

String p="\\W|\\w+"

Pattern pattern = Pattern.compile(p);
Matcher matcher = pattern.matcher(str);
List<String> matchlist = new ArrayList<String>();

while(matcher.find()) {
    matchlist.add(matcher.group(0));
}

产生:

['"', 'I', '"', ' ', 'am_the', ' ', '2nd', ' ', '"', 'best', '"', '.']

然后您可以决定如何在您的代码中处理。

不,这不会为您提供一个万能的正则表达式来匹配您上面列出的两种情况,但根据我的经验,正则表达式并不是真正的最佳工具您需要的句法分析,因为它们要么缺乏涵盖所有可能的情况所需的表达能力,要么,而且更有可能的是,它们很快变得对大多数人来说过于复杂,但真正的 RegExp maven 完全理解。

【讨论】:

  • 在阅读了上面约翰的回答并看到它有效之后,我将尝试使用它。但是,我非常感谢这里的洞察力。我是非常新的词法分析,你说得非常正确,如果你试图找到一个包罗万象的问题,问题可能会变得非常大。我一定会从你的答案中学习未来。谢谢
猜你喜欢
  • 1970-01-01
  • 2016-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多