在Java中从列表中提取子字符串

时间:2015-12-11 16:04:13

标签: java regex string substring

如果我有一个父字符串(我们称之为output),其中包含一个变量赋值列表,如此...

status.availability-state available
status.enabled-state enabled
status.status-reason The pool is available

我想在给定变量名称的情况下提取该列表中每个变量的值,即status.availability-statestatus.enabled-statestatus.status-reason之后的空格后面的子字符串,这样我最后得到三个不同的变量赋值,使得以下每个字符串比较都成立......

String availability = output.substring(TODO);
String enabled = output.substring(TODO);
String reason = output.substring(TODO);

availability.equals("available");
enabled.equals("enabled");
reason.equals("The pool is available");

最简单的方法是什么?我应该使用substring吗?

5 个答案:

答案 0 :(得分:2)

这有点棘手,因为您需要将值分配给特定变量 - 您不能只在Java中拥有变量键的映射。

我会考虑用开关来做这件事:

for (String line : output.split('\n')) {
  String[] frags = line.split(' ', 2);  // Split the line in 2 at the space.
  switch (frags[0]) {  // This is the "key" of the variable.
    case "status.availability-state":
      availability = frags[1];  // This assigns the "value" to the relevant variable.
      break;
    case "status.enabled-state":
      enabled = frags[1];
      break;
    // ... etc
  }
}

它不是很漂亮,但你没有太多的选择。

答案 1 :(得分:2)

这里似乎有两个问题 - 如何解析字符串,以及如何按名称分配变量。

一次解决一个字符串解析:

  • 首先编写一个程序,一次读取一行,然后在循环体中输出每一行。 String.split()StringTokenizer是两个选项。
  • 接下来通过编写处理一行的方法来增强此功能。这里使用相同的工具来分隔空格。
  • 您现在应该有一个程序可以为每行输入打印name: status.availability-state, value: available

接下来,您要求根据参数名称以编程方式分配变量。

在运行时没有合法的方法来查看变量的名称(好的,Java 8反射有方法,但不应该在没有充分理由的情况下使用它)。

因此,您可以做的最好的事情是使用switchif声明:

switch(name) {
    case status.availability-state:
        availability = value;
        break;
    ... etc.
}

但是,无论何时使用switchif,您都应该考虑是否有更好的方法。

是否有任何理由无法将这些变量转换为Map条目?

 configMap.add(name,value);

然后阅读:

 doSomethingWith(configMap.get("status.availability");

这就是地图的用途。使用它们。

这与使用名为person1person2person3的变量的新手错误类似,而不是使用数组。最终他们会问“我如何从25号到变量person25?” - 答案是,你不能,但数组或列表使它变得容易。 people[number]people.get(number)

答案 2 :(得分:1)

有效的替代方法是将字符串拆分为\n并添加到Map。例如:

String properties = "status.availability-state available\nstatus.enabled-state enabled\nstatus.status-reason The pool is available";

Map<String, String> map = Arrays.stream(properties.split("\n"))
                    .collect(Collectors.toMap(s -> s.split(" ")[0], s -> s.split(" ", 2)[1]));

System.out.println(map.get("status.status-reason"));

应输出The pool is available

答案 3 :(得分:0)

此循环将匹配并提取变量,然后您可以根据需要分配它们:

Pattern regex = Pattern.compile("status\\.(.*?)-.*? ([a-z]+)");
Matcher matcher = regex.matcher(output);
while (matcher.find()) {
    System.out.println(matcher.group(1) + "=" + matcher.group(2));
}

status\\.匹配“状态。”

(.*?)匹配任何字符序列,但不贪婪,并捕获它们

-.*匹配破折号,任何字符,空格

([a-z]+)匹配任何小写字母字符串,并捕获它们

答案 4 :(得分:0)

这是一种方法:

Map<String, String> properties = getProperties(propertiesString);

availability = properties.get("availability-state");
enabled = properties.get("enabled-state");
reason = properties.get("status-reason");

// ...

public void getProperties(String input) {
    Map<String, String> properties = new HashMap<>();
    String[] lines = output.split("\n");

    for (String line : lines) {
        String[] parts = line.split(" ");
        int keyStartIndex = parts[0].indexOf(".") + 1;
        int spaceIndex = parts[1].indexOf(" ");
        string key = parts[0].substring(keyStartIndex, spaceIndex);
        properties.put(key, parts[1]);
    }

    return properties;
}

就设置这些值的代码而言,这似乎更直接,因为每个值都设置为映射中的值,而不是迭代某些字符串列表并查看它是否包含一个特定的价值,并根据它做不同的事情。

这是为主要用例设计的,即字符串是在运行时在内存中创建的。如果在外部文件中创建属性,则此代码仍然有效(在内存中创建所需的String之后),但使用Properties文件或Scanner可能更好。 }。