Java 按空格分隔字符串

Java 按空格分隔字符串,java,string,parsing,split,word-spacing,Java,String,Parsing,Split,Word Spacing,我需要用java中的空格分隔单词,所以我使用了.split函数来实现如下所示的效果 String keyword = "apple mango "; String keywords [] = keyword .split(" "); 上面的代码工作正常,但唯一的问题是我的关键字有时会包含像“jack fruit”,“ice cream”这样的关键字,并带有双引号,如下所示 String keyword = "apple mango \"jack fruit\" \"ice cream\"";

我需要用java中的空格分隔单词,所以我使用了
.split
函数来实现如下所示的效果

String keyword = "apple mango ";
String keywords [] = keyword .split(" ");
上面的代码工作正常,但唯一的问题是我的关键字有时会包含像“jack fruit”“ice cream”这样的关键字,并带有双引号,如下所示

String keyword = "apple mango \"jack fruit\" \"ice cream\"";
在这种情况下,我需要在关键字数组中获得4个单词,如苹果、芒果、菠萝、冰淇淋


有人能告诉我一些解决方案吗?这个解决方案很有效,但我确信这对性能/资源来说不是最好的。当你有超过两个单词的水果时,它也会起作用。请随意编辑或优化我的代码

public static void main(String[] args) {
        String keyword = "apple mango \"jack fruit\" \"ice cream\" \"one two three\"";
        String[] split = custom_split(keyword);
        for (String s : split) {
            System.out.println(s);
        }
    }

    private static String[] custom_split(String keyword) {
        String[] split = keyword.split(" ");
        ArrayList<String> list = new ArrayList<>();
        StringBuilder temp = new StringBuilder();
        boolean multiple = false;
        for (String s : split) {
            if (s.startsWith("\"")) {
                multiple = true;
                s = s.replaceAll("\"", "");
                temp.append(s);
                continue;
            }
            if (s.endsWith("\"")) {
                multiple = false;
                s = s.replaceAll("\"", "");
                temp.append(" ").append(s);
                list.add(temp.toString());
                temp = new StringBuilder();
                continue;
            }
            if (multiple) {
                temp.append(" ").append(s);
            } else {
                list.add(s);
            }
        }
        String[] result = new String[list.size()];
        for (int i = 0; i < list.size(); i++) {
            result[i] = list.get(i);
        }
        return result;
    }
publicstaticvoidmain(字符串[]args){
String关键字=“苹果芒果\”杰克水果\“\”冰淇淋\“\”一二三\”;
字符串[]拆分=自定义拆分(关键字);
用于(字符串s:拆分){
系统输出打印项次;
}
}
私有静态字符串[]自定义分割(字符串关键字){
String[]split=关键字.split(“”);
ArrayList=新建ArrayList();
StringBuilder temp=新的StringBuilder();
布尔倍数=假;
用于(字符串s:拆分){
如果(s.startsWith(“\”)){
多重=真;
s=s.replaceAll(“\”,“);
临时附加;
继续;
}
如果(s.endsWith(“\”)){
多重=假;
s=s.replaceAll(“\”,“);
临时追加(“”)追加;
添加(temp.toString());
temp=新的StringBuilder();
继续;
}
如果(多个){
临时追加(“”)追加;
}否则{
列表。添加(s);
}
}
字符串[]结果=新字符串[list.size()];
对于(int i=0;i
您不能使用
String.split()
。您需要为目标标记找到一个正则表达式,并通过匹配器收集它们,如下所示:

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

    List<String> tokens = new ArrayList<>();
    Matcher m = token.matcher( "apple mango \"jack fruit\" \"ice cream\"" );
    while( m.find() )
        tokens.add( m.group() );
final Pattern token=Pattern.compile(“[^\”\\s]+\\“[^\”]*\”);
List tokens=new ArrayList();
Matcher m=token.Matcher(“苹果芒果”“杰克水果”“冰淇淋”);
while(m.find())
添加(m.group());

我会使用一个正则表达式和两个捕获组,每个模式一个。我不知道还有别的办法

    String keyword = "apple mango \"jack fruit\" \"ice cream\"";
    Pattern p = Pattern.compile("\"?(\\w+\\W+\\w+)\"|(\\w+)");      
    Matcher m = p.matcher(keyword);
    while (m.find()) {
        String word = m.group(1) == null ? m.group(2) : m.group(1);
        System.out.println(word);
    }

这将拆分引号上的字符串,然后再按空格拆分偶数成员

    String keyword = "apple mango \"jack fruit\" \"ice cream\"";
    String splitQuotes [] = keyword.split("\"");

    List<String> keywords = new ArrayList<>();

    for (int i = 0; i < splitQuotes.length; i++) {
        if (i % 2 == 0) {
            Collections.addAll(keywords, splitQuotes[i].split(" "));
        } else {
            keywords.add(splitQuotes[i]);
        }
    }
String keyword=“苹果芒果”“杰克水果”“冰淇淋”;
字符串splitQuotes[]=关键字.split(“\”);
列表关键字=新建ArrayList();
for(int i=0;i
这可能需要正则表达式来检查引号,只是说;)我的一般感觉是,这种问题实际上可能适合一个解析器,而不是一个正则表达式。看到这一个,我删除了我的解决方案,我不知道为什么我没有考虑使用两个组……虽然OP可能已经放弃了线程,但这个解决方案不是他是最优雅的一个。如果有人错误地在最后只加了一个双引号,比如
苹果芒果“
我想如果你真的需要更严格的条件解析,你就必须拿出重炮。比如JavaCC,如果你想把它发挥到极致,并且能够检测到这种错误。正则表达式并没有这样的逻辑。如果你扔扳手,它会表现得很滑稽。@mprivat如果关键字是
String关键字=“\'ice cream\'192.168.214.125”由于
冰激凌
192.168.214.125
反馈-)不起作用,它没有给出正确的结果。你错过了杰克水果,因为你只抓了一个group@MuratK. 很抱歉,我的匹配正则表达式有一个小问题,我最初是在手机上回答这个问题的。它正在工作。@TimBiegeleisen,如果关键字是
String关键字=“\”冰淇淋\”192.168.214.125”
它没有给出正确的结果,因为
冰激凌
192.168.214.125
@AlexMan I在关键字上添加了一个额外的
trim()
,以处理此边缘情况。只有在引号“”的内部,关键字中才能有空单元格。如果您的意思是当两个引号一个接一个(如“jack fruit\”和“ice cream\”)时,它将添加它们,那么它将只调用addAll并添加空字符串数组,因此不会影响结果。或者还有其他我没有看到的情况?
List<String> parts = new ArrayList<>();
String keyword = "apple mango \"jack fruit\" \"ice cream\"";

// first use a matcher to grab the quoted terms
Pattern p = Pattern.compile("\"(.*?)\"");      
Matcher m = p.matcher(keyword);
while (m.find()) {
    parts.add(m.group(1));
}

// then remove all quoted terms (quotes included)
keyword = keyword.replaceAll("\".*?\"", "")
                 .trim();

// finally split the remaining keywords on whitespace
if (keyword.replaceAll("\\s", "").length() > 0) {
    Collections.addAll(parts, keyword.split("\\s+"));
}

for (String part : parts) {
    System.out.println(part);
}
jack fruit
ice cream
apple
mango