【问题标题】:Regex to match words between single or double quotes in a string正则表达式匹配字符串中单引号或双引号之间的单词
【发布时间】:2012-09-26 08:56:31
【问题描述】:

我正在寻找正确的正则表达式来为我提供以下结果:

  • 需要将单引号/双引号括起来的单词分组
  • 当字符串中没有其他单引号时,需要继续打印单引号
  • 当没有被单引号/双引号包围时 - 按空格分隔

我目前有:

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

...但以下示例并不完全有效。 谁能帮我解决这个问题?

示例:

  • 富吧
    • group1: foo
    • group2: 酒吧
    • 说明:空间分割
  • “富吧”
    • group1: 富吧
    • 说明:用双引号括起来,所以分组 foo 和 bar,但不要打印双引号
  • '富酒吧'
    • group1: 富吧
    • 说明:同上,但用单引号
  • '富酒吧
    • group1: 'foo
    • group2: 酒吧
    • 说明:按空格分割并保留单引号
  • "'富吧"
    • group1: '富吧
    • 说明:用双引号括起来,因此将 'foo 和 bar 分组并保留单引号
  • 富酒吧'
    • group1: foo
    • group2: 酒吧'
  • 富吧"
    • group1: foo
    • group2: 酒吧"
  • “foo bar”“堆栈溢出”
    • group1: 富吧
    • group2:堆栈溢出
  • “foo' bar”“堆栈溢出”怎么办
    • group1: foo' 酒吧
    • group2:堆栈溢出
    • group3:如何
    • group4:做
    • group5:你
    • 组6:做

【问题讨论】:

  • 我发布了一个here,这可能是一个好的开始。它不处理单引号和逗号而不是空格,但它可能是一个好的开始。一个好处是它实际上是如何工作的。
  • 谢谢,但是 Keppil 用户给了我正确的解决方案 :-)
  • Keppil 的解决方案涵盖了您的测试用例,但请注意,它不允许诸如“包含“引号”的字符串”之类的情况,但如果您不需要,那么很高兴认识您有答案。

标签: java regex


【解决方案1】:

我不确定您是否可以在一个 Matcher.match 调用中执行此操作,但您可以通过循环来执行此操作。
这段代码通过重复使用Matcher.find() 解决了上面提到的所有情况:

Pattern pattern = Pattern.compile("\"([^\"]+)\"|'([^']+)'|\\S+");
List<String> testStrings = Arrays.asList("foo bar", "\"foo bar\"","'foo bar'", "'foo bar", "\"'foo bar\"", "foo bar'", "foo bar\"", "\"foo bar\" \"stack overflow\"", "\"foo' bar\" \"stack overflow\" how do you do");
for (String testString : testStrings) {
    int count = 1;
    Matcher matcher = pattern.matcher(testString);
    System.out.format("* %s%n", testString);
    while (matcher.find()) {
        System.out.format("\t* group%d: %s%n", count++, matcher.group(1) == null ? matcher.group(2) == null ? matcher.group() : matcher.group(2) : matcher.group(1));
    }
}

这打印:

* foo bar
    * group1: foo
    * group2: bar
* "foo bar"
    * group1: foo bar
* 'foo bar'
    * group1: foo bar
* 'foo bar
    * group1: 'foo
    * group2: bar
* "'foo bar"
    * group1: 'foo bar
* foo bar'
    * group1: foo
    * group2: bar'
* foo bar"
    * group1: foo
    * group2: bar"
* "foo bar" "stack overflow"
    * group1: foo bar
    * group2: stack overflow
* "foo' bar" "stack overflow" how do you do
    * group1: foo' bar
    * group2: stack overflow
    * group3: how
    * group4: do
    * group5: you
    * group6: do

【讨论】:

  • 就是这样!你真是个天才! :-)。谢谢你帮我做这个
  • 在这里测试没有问题:regexplanet.com/advanced/java/index.html(你必须删除Java字符串转义)
  • @SJuan76,我正在回复您的原始评论。您的新示例可以说超出了问题要求的范围。
  • @dan1111 你是对的......一个更好的例子是 foo'"bar slashdot"
  • @SJuan76,据我了解,问题假设每个项目,无论是否引用,都将用空格分隔。鉴于这个假设,我相信这是一个强大的正则表达式。我理解您关于使用正则表达式进行解析的危险的一般观点,但在像这样一个相当简单的情况下,我没有看到问题。
【解决方案2】:

只要你有配对(让它是引号或大括号),你就会离开正则表达式的领域并进入需要解析器的语法领域。

我会把ultimate answer to this question留给你

更新:

再解释一下。

语法通常表示为:

construct -> [set of constructs or terminals]

例如,引号

doblequotedstring := " simplequotedstring "
simplequotedstring := string ' string
                      | string '
                      | ' string
                      | '

这是一个简单的例子;网上会有合适的语法例子供引用。

我为此使用了 aflex 和 ajacc(对于 Ada;在 Java 中存在 jflex 和 jjacc)。您将标识符列表传递给 aflex,生成一个输出,将该输出和语法传递给 ajacc,然后您将获得一个 Ada 解析器。由于我使用它们已经很长时间了,我不知道是否有更简化的解决方案,但基本上它需要相同的输入。

【讨论】:

  • 我不想在 RegEx 中解析 HTML 字符串。我正在尝试对单词进行分组并将它们拆分为单/双引号和空格。我想这些是我们使用...正则表达式的原因,不是吗?在我看来,别无选择。
  • 阅读我的评论。匹配引号意味着您正在使用“正确”的语法(所有正则表达式都是语法,但并非所有语法都是正则表达式;您的示例不是正则表达式)。现在阅读链接的答案。 没有办法用正则表达式解析“正确”的语法。您可以将正则表达式用于恰好是正则表达式的语法子集(例如,检测字符串是否以引号开头和结尾),但仅此而已。这是数学上的不可能。
  • 顺便说一句,我链接的答案具有这种风格和很多赞成票,因为当您告诉某人他需要语法时,通常的答案是“但我想用正则表达式来做“...
  • 我对这个答案投了反对票,因为它没有帮助。为此使用 RegEx 是完全合理的。这个问题和解析 HTML 有天壤之别。
  • @dan1111,做我的客人,给我看正则表达式。我会喜欢它,如果它有效
猜你喜欢
  • 2016-10-06
  • 2018-06-15
  • 1970-01-01
  • 1970-01-01
  • 2018-04-08
  • 2020-10-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多