将字符串拆分为java

时间:2017-07-25 09:33:02

标签: java regex string split

我的字符串就像:

String s = "args: val args1: val1 args2: val3 /*...argsn: valn*/";
///*...argsn: valn*/ means that the string may contain n number of args and vals

其中:  args os s word或我已经知道的单词组合  val可以是单个单词,也可以是包含单词和符号的全文,如":"或"," ...... 我想要做的是显示任何给定的' args'显示它' val'

这是我试过的:

public class Main {
    public static void main(String[] args) {
        String s = "arg1: val1 arg2: val2 arg3: va:l3";

        String[] rawPairs = s.replace(": ", ":").split(" ");

        Map<String, String> argsMap = Arrays.stream(rawPairs).collect(toMap(pair -> pair.substring(0, pair.indexOf(":")), pair -> pair.substring(pair.indexOf(":") + 1)));
        System.out.println(argsMap.get("arg3"));
        System.out.println(argsMap.get("arg5"));

    }
}

如果&#39; val&#39;是一个单词但是一旦它成为文本我就会得到这个输入的错误:

String s = "arg1: val1 arg2: val2 is a sentence  arg3: va:l3";

错误:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(String.java:1967)
at mainTest.lambda$main$0(mainTest.java:306)
at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:948)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at mainTest.main(mainTest.java:306)

5 个答案:

答案 0 :(得分:4)

使用正则表达式尝试:

String s = "arg1 : val1 arg2 : val2 is a sentence  arg3 : va:l3";
Map<String, String> argMap = new HashMap<String, String>();
Matcher argMatcher = Pattern.compile("arg\\d*\\s?:\\s.*?(?=(\\s+arg\\d|$))").matcher(s);

while (argMatcher.find())
{
    String match = argMatcher.group();
    String[] pair = match.split("\\s\\:\\s");
    argMap.put(pair[0], pair[1]);
}

System.out.println(argMap);

打印:

{arg3=va:l3, arg2=val2 is a sentence, arg1=val1}

答案 1 :(得分:2)

您尝试解析的表达式不明确。

例如,您无法区分food: bread score: 10,根据您的定义,arg1:food可能意味着:

  • val1:breadarg2:scoreval2:10arg1:food
  • val1:bread score: 10:(因为 {"arg1":"val1","arg2":"val2",...} 可以是价值的一部分)

只要存在诸如此类的模糊情况,您将无法可靠地拆分字符串。

您需要找到一个更好,更可靠的代码来表示您要解析的数据。

例如,您可以将数据表示为json字符串

let xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {...}

答案 2 :(得分:1)

尝试使用Pattern&amp; Matcher如下:

String s = "arg1 : val1 arg2 : val2 arg3 : va:l3";

if (s.contains("arg")) {

  Pattern pattern = Pattern.compile("arg1 :(.*?)arg2");
  Matcher matcher = pattern.matcher(s);
  while (matcher.find()) {
       System.out.println(matcher.group(1));                                
       String value = matcher.group(1);
       System.out.println(value);   
  }
}

以上代码可以获取"arg1 :""arg2"之间的所有字符。按照你的要求做。

答案 3 :(得分:1)

由于我们仍然不知道字符串的确切含义,我将给出两个非常相似的解决方案:

arg

表示字符串包含 String s = "arg1: val1 arg2: val2 arg3: va:l3"; Map<String, String> map = new LinkedHashMap<String, String>(); String[] splitted = s.split("args\\d*:"); for (int i = 1; i < splitted.length; i++) { map.put(String.valueOf("arg" + (i)), splitted[i].trim()); } System.out.println(map);

args

表示字符串包含{{1}}的情况。此解决方案还会填充地图中的数据以分别访问密钥和值

答案 4 :(得分:1)

有点太晚了,但这里的代码真正将原始字符串解析为以下内容:

arg1: val1 
arg2: val2 
arg3: 
va:l3

只是有点阐述

public static void main(String[] argv) {
    String argStr = "arg1: val1 arg2: val2 arg3: va:l3";
    Pattern p = Pattern.compile("(^|\\s)(\\w+:)");
    Matcher m;
    LinkedList<StringBuilder>  argLst = new LinkedList<>();

    while ((m = p.matcher(argStr)).find()) {
        if (m.start(1) > 0) 
            argLst.getLast().append(argStr.substring(0, m.start(1)));
        if (!argLst.isEmpty())
            argLst.getLast().append(m.group(1));
        argLst.add(new StringBuilder(m.group(2)));
        argStr = argStr.substring(m.end(2));
    }
    if (!argStr.isEmpty() && !argLst.isEmpty())  
        argLst.getLast().append(argStr);


    for (StringBuilder sb: argLst) 
        System.out.println(sb.toString());
}