在空格上拆分字符串,除非使用双引号但双引号可以附加前面的字符串

时间:2018-05-03 09:20:58

标签: java regex split

我需要在Java中拆分一个字符串(首先删除引号之间的空格,然后在空格处拆分。)

  

“abc test = \”x y z \“magic = \”hello \“hola”

变为:

首先:

  

“abc test = \”xyz \“magic = \”hello \“hola”

然后:

  • ABC
  • 测试= “XYZ”
  • 魔法= “你好”
  • HOLA

场景: 我从输入中得到一个类似上面的字符串,我想将它分成上面的部分。一种方法是先删除引号之间的空格然后在空格处拆分。引号之前的字符串使它复杂化。第二个是在空格处拆分,但如果在内部引用则不拆分,然后从单个拆分中删除空格。我尝试使用“\”([^ \“] +)\”“来捕获引号,但我无法捕获引号内的空格。我尝试了一些但没有运气。

4 个答案:

答案 0 :(得分:4)

我们可以使用正式模式匹配器来完成此操作。以下答案的秘诀是使用不常用的Matcher#appendReplacement方法。我们在每场比赛中暂停,然后附加两个引号内出现的任何内容的自定义替换。自定义方法removeSpaces()从每个引用的术语中删除所有空格。

public static String removeSpaces(String input) {
    return input.replaceAll("\\s+", "");
}

String input = "abc test=\"x y z\" magic=\" hello \" hola";
Pattern p = Pattern.compile("\"(.*?)\"");
Matcher m = p.matcher(input);
StringBuffer sb = new StringBuffer("");
while (m.find()) {
    m.appendReplacement(sb, "\"" + removeSpaces(m.group(1)) + "\"");
}
m.appendTail(sb);

String[] parts = sb.toString().split("\\s+");
for (String part : parts) {
    System.out.println(part);
}

abc
test="xyz"
magic="hello"
hola

Demo

正如上面的评论暗示的那样,这里的一个重要警告是我们真正使用正则表达式引擎作为一个基本的解析器。要查看我的解决方案快速失败的位置,只需从引用的术语中删除其中一个引号。但是,如果你确定你输入的信息很好,就像你向我们展示的那样,这个答案可能适合你。

答案 1 :(得分:1)

我想提一下java 9' Matcher.replaceAll lambda扩展名:

// Find quoted strings and remove there whitespace:
s = Pattern.compile("\"[^\"]*\"").matcher(s)
    .replaceAll(mr -> mr.group().replaceAll("\\s", ""));

// Turn the remaining whitespace in a comma and brace all.
s = '{' + s.trim().replaceAll("\\s+", ", ") + '}';

答案 2 :(得分:0)

可能另一个答案是更好但我仍然写了所以我会在这里发布;)它需要一个不同的方法

public static void main(String[] args) {
        String test="abc test=\"x y z\"   magic=\"  hello   \"   hola";
          Pattern pattern = Pattern.compile("([^\\\"]+=\\\"[^\\\"]+\\\" )");
            Matcher matcher = pattern.matcher(test);
            int lastIndex=0;
            while(matcher.find()) {
                String[] parts=matcher.group(0).trim().split("=");

                boolean newLine=false;
                for (String string : parts[0].split("\\s+")) {
                    if(newLine)
                        System.out.println();
                    newLine=true;
                    System.out.print(string);
                }
                System.out.println("="+parts[1].replaceAll("\\s",""));
                lastIndex=matcher.end();
            }
            System.out.println(test.substring(lastIndex).trim());           
    }

结果是

abc
test="xyz"
magic="hello"
hola

答案 3 :(得分:0)

听起来你想写一个基本的解析器/ Tokenizer。我敢打赌,在你制作出能够处理这种结构中漂亮印刷的东西之后,你很快就会想要开始验证是否存在任何不匹配的"

但实际上,对于这个特定的问题,你有几个阶段,而Java有一个内置的tokenizer,它可以证明是有用的。

import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.stream.Collectors;

public class Q50151376{

    private static class Whitespace{
        Whitespace(){ }
        @Override
        public String toString() {
            return "\n";
        }
    }

    private static class QuotedString {
        public final String string;

        QuotedString(String string) {
            this.string = "\"" + string.trim() + "\"";
        }

        @Override
        public String toString() {
            return string;
        }
    }

    public static void main(String[] args) {
        String test = "abc test=\"x y z\" magic=\" hello \" hola";
        StringTokenizer tokenizer = new StringTokenizer(test, "\"");
        boolean inQuotes = false;
        List<Object> out = new LinkedList<>();
        while (tokenizer.hasMoreTokens()) {
            final String token = tokenizer.nextToken();
            if (inQuotes) {
                out.add(new QuotedString(token));
            } else {
                out.addAll(TokenizeWhitespace(token));
            }
            inQuotes = !inQuotes;
        }

        System.out.println(joinAsStrings(out));
    }

    private static String joinAsStrings(List<Object> out) {
        return out.stream()
                .map(Object::toString)
                .collect(Collectors.joining());
    }

    public static List<Object> TokenizeWhitespace(String in){
        List<Object> out = new LinkedList<>();
        StringTokenizer tokenizer = new StringTokenizer(in, " ", true);

        boolean ignoreWhitespace = false;
        while (tokenizer.hasMoreTokens()){
            String token = tokenizer.nextToken();
            boolean whitespace = token.equals(" ");
            if(!whitespace){
                out.add(token);
                ignoreWhitespace = false;
            } else if(!ignoreWhitespace) {
                out.add(new Whitespace());
                ignoreWhitespace = true;
            }
        }
        return out;
    }

}