提取字符串的属性

时间:2015-06-03 21:35:45

标签: java string attributes extract

我必须在这里处理由脏设计引起的问题。我得到一个字符串列表,并希望解析它的属性。不幸的是,我无法更改创建这些String的源。

示例:

String s = "type=INFO, languageCode=EN-GB, url=http://www.stackoverflow.com, ref=1, info=Text, that may contain all kind of chars., deactivated=false"

现在我要提取属性typelanguageCodeurlrefinfodeactivated

这里的问题是字段info,其文本不受引号的限制。此字段中也可能出现逗号,因此我无法在字符串末尾使用逗号来查找结束的位置。

另外,这些字符串并不总是包含所有属性。始终存在typeinfodeactivated,其余为可选。

有什么建议我可以解决这个问题吗?

3 个答案:

答案 0 :(得分:4)

一种可能的解决方案是在输入中搜索=个字符,然后将其前面的单个字作为字段名称 - 似乎所有字段名称都是单个字(无空格)。如果是这种情况,那么您可以将=之后的所有内容,直到下一个字段名称(将,分开)作为值。

这假设该值不能包含=

修改

作为处理嵌入式=的一种可能方法,您可以查看它前面的单词是否是您已知的字段名称 - 如果不是,您可以将=视为嵌入字符而不是运营商。但是,这假定您有一组固定的已知字段(其中一些可能并不总是出现)。如果您知道字段名称区分大小写,则可以放宽此假设。

答案 1 :(得分:2)

假设元素的顺序是固定的,你可以使用像这样的正则表达式编写解决方案

String s = "type=INFO, languageCode=EN-GB, url=http://www.stackoverflow.com, ref=1, info=Text, that may contain all kind of chars., deactivated=false";

String regex = //type, info and deactivated are always present
          "type=(?<type>.*?)"
        + "(?:, languageCode=(?<languageCode>.*?))?"//optional group
        + "(?:, url=(?<url>.*?))?"//optional group
        + "(?:, ref=(?<rel>.*?))?"//optional group
        + ", info=(?<info>.*?)"
        + ", deactivated=(?<deactivated>.*?)";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);
if(m.matches()){
    System.out.println("type -> "+m.group("type"));
    System.out.println("languageCode -> "+m.group("languageCode"));
    System.out.println("url -> "+m.group("url"));
    System.out.println("rel -> "+m.group("rel"));
    System.out.println("info -> "+m.group("info"));
    System.out.println("deactivated -> "+m.group("deactivated"));
}

输出:

type -> INFO
languageCode -> EN-GB
url -> http://www.stackoverflow.com
rel -> 1
info -> Text, that may contain all kind of chars.
deactivated -> false

编辑:版本2 正则表达式搜索oneOfPossibleKeys=valuevalue结尾的地方:

  • , oneOfPossibleKeys=
  • 或其后面的字符串结尾(由$表示)。

代码:

String s = "type=INFO, languageCode=EN-GB, url=http://www.stackoverflow.com, ref=1, info=Text, that may contain all kind of chars., deactivated=false";

String[] possibleKeys = {"type","languageCode","url","ref","info","deactivated"};
String keysStrRegex = String.join("|", possibleKeys);
//above will contain type|languageCode|url|ref|info|deactivated

String regex = "(?<key>\\b(?:"+keysStrRegex+")\\b)=(?<value>.*?(?=, (?:"+keysStrRegex+")=|$))";
    // (?<key>\b(?:type|languageCode|url|ref|info|deactivated)\b)
    // =
    // (?<value>.*?(?=, (?:type|languageCode|url|ref|info|deactivated)=|$))System.out.println(regex);

Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(s);


while(m.find()){
    System.out.println(m.group("key")+" -> "+m.group("value"));
}

输出:

type -> INFO
languageCode -> EN-GB
url -> http://www.stackoverflow.com
ref -> 1
info -> Text, that may contain all kind of chars.
deactivated -> false

答案 2 :(得分:1)

您可以使用正则表达式捕获所有&#34;固定的&#34;分组并使用Cat B.的剩余部分。如果["Cat B.", 3, 19, 0, 1, 21], 部分包含infoinfo字符,这甚至可以使用。这是一个简单的例子(使用Python,但这应该不是问题......)。

,

如果这些元素中的任何一个是可选的,您可以在这些组之后添加=,并使逗号可选。如果订单可能不同,那么它就更复杂了。在这种情况下,不是使用一个RegEx一次捕获所有内容,而是使用多个RegEx来捕获各个属性,然后在匹配下一个属性之前删除(替换为>>> p = r"(type=[A-Z]+), (languageCode=[-A-Z]+), (url=[^,]+), (ref=\d), (info=.+?), (deactivated=(?:true|false))" >>> s = "type=INFO, languageCode=EN-GB, url=http://www.stackoverflow.com, ref=1, info=Text, that may contain all kind of chars, even deactivated=true., deactivated=false" >>> re.search(p, s).groups() ('type=INFO', 'languageCode=EN-GB', 'url=http://www.stackoverflow.com', 'ref=1', 'info=Text, that may contain all kind of chars, even deactivated=true.', 'deactivated=false') )字符串中的那些属性。最后,匹配?

进一步考虑,鉴于这些属性可能有任何顺序,从一个关键字到下一个关键字捕获所有内容可能更有希望,无论其实际内容如何,​​与Pshemo的解决方案非常相似:< / p>

''

但是,这也可能在一些非常模糊的情况下失败,例如:如果info属性包含keys = "type|languageCode|url|ref|info|deactivated" p = r"({0})=(.+?)(?=\, (?:{0})=|$)".format(keys) matches = re.findall(p, s) 之类的内容,包括逗号。然而,似乎没有办法解决这些含糊之处。如果您有一个类似info的字符串,它是否包含一个', ref=foo'属性,或三个,或者根本没有?