1

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

  • 它需要对单/双引号包围的单词进行分组
  • 当字符串中没有其他单引号时,它需要继续打印单引号
  • 当没有被单引号/双引号包围时 - 按空格分割

我目前有:

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

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

例子:

  • 富吧
    • 组1:富
    • 组2:酒吧
    • 描述:空间分割
  • “富吧”
    • group1: 富吧
    • 描述:被双引号包围,所以分组 foo 和 bar,但不要打印双引号
  • '富吧'
    • group1: 富吧
    • 描述:同上,但用单引号
  • '富吧
    • 组1:'富
    • 组2:酒吧
    • 描述:按空格分割并保留单引号
  • “'富吧”
    • group1: '富吧
    • 描述:被双引号包围,所以将 'foo 和 bar 分组并保留单引号
  • 富吧'
    • 组1:富
    • 组2:酒吧'
  • 富吧”
    • 组1:富
    • 组2:酒吧”
  • “foo bar” “堆栈溢出”
    • group1: 富吧
    • group2:堆栈溢出
  • “foo' bar” “堆栈溢出” 你怎么办
    • group1: foo' 酒吧
    • group2:堆栈溢出
    • 第三组:如何
    • 组4:做
    • 第五组:你
    • 第六组:做
4

2 回答 2

7

我不确定你是否可以在一次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
于 2012-10-05T08:51:25.383 回答
1

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

我会给你这个问题的最终答案

更新:

多一点解释。

语法通常表示为:

construct -> [set of constructs or terminals]

例如,对于引号

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

这是一个简单的例子;将有适当的语法示例在互联网上引用。

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

于 2012-10-05T08:20:29.950 回答