提取字符串的属性
Extract attributes of an string
我必须在这里处理一个由肮脏的设计引起的问题。我得到一个字符串列表,想从中解析属性。不幸的是,我无法更改创建这些字符串的来源。
示例:
String s = "type=INFO, languageCode=EN-GB, url=http://www.whosebug.com, ref=1, info=Text, that may contain all kind of chars., deactivated=false"
现在我想提取属性 type
、languageCode
、url
、ref
、info
和 deactivated
。
这里的问题是字段info
,其文本不受引号限制。此字段中也可能出现逗号,因此我不能在字符串末尾使用逗号来找出结束位置。
此外,这些字符串并不总是包含所有属性。 type
、info
和 deactivated
总是存在的,其余的是可选的。
有什么解决这个问题的建议吗?
一种可能的解决方案是在输入中搜索 =
个字符,然后将其前面的单个单词作为字段名称 - 似乎您所有的字段名称都是单个单词(无空格)。如果是这种情况,则可以将 =
之后直到下一个字段名称(用于分隔 ,
)的所有内容作为值。
这假定该值不能包含 =
。
编辑:
作为处理嵌入 =
的一种可能方法,您可以查看它前面的单词是否是您已知的字段名称 - 如果不是,您可以将 =
视为一个嵌入字符而不是运算符。然而,这假设您有一组固定的已知字段(其中一些可能不会总是出现)。如果您知道字段名称区分大小写,则可能会放宽此假设。
您可以使用正则表达式,捕获所有 "fixed" 组并使用 info
的剩余部分。如果 info
部分包含 ,
或 =
字符,这甚至应该有效。这是一些简单的示例(使用 Python,但这应该不是问题...)。
>>> p = r"(type=[A-Z]+), (languageCode=[-A-Z]+), (url=[^,]+), (ref=\d), (info=.+?), (deactivated=(?:true|false))"
>>> s = "type=INFO, languageCode=EN-GB, url=http://www.whosebug.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.whosebug.com',
'ref=1',
'info=Text, that may contain all kind of chars, even deactivated=true.',
'deactivated=false')
如果这些元素中的任何一个是可选的,您可以在这些组之后放置一个 ?
,并将逗号设为可选。如果顺序可以不同,那就更复杂了。在这种情况下,不是使用一个 RegEx 一次捕获所有内容,而是使用多个 RegEx 捕获各个属性,然后在匹配下一个属性之前删除(替换为 ''
)字符串中的那些属性。最后,匹配 info
.
进一步考虑,考虑到这些属性可以有任何顺序,更有希望捕获从一个关键字到下一个关键字的所有内容,而不考虑其实际内容,这与 Pshemo 的解决方案非常相似:
keys = "type|languageCode|url|ref|info|deactivated"
p = r"({0})=(.+?)(?=\, (?:{0})=|$)".format(keys)
matches = re.findall(p, s)
但这也可能在一些非常模糊的情况下失败,例如如果 info
属性包含类似 ', ref=foo'
的内容,包括逗号。然而,似乎没有办法解决这些歧义。如果你有一个像 info=in this string, ref=1, and in another, ref=2, ref=1
这样的字符串,它包含一个 ref
属性,还是三个,或者根本不包含 none?
假设元素的顺序是固定的,您可以像这样使用正则表达式编写解决方案
String s = "type=INFO, languageCode=EN-GB, url=http://www.whosebug.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.whosebug.com
rel -> 1
info -> Text, that may contain all kind of chars.
deactivated -> false
编辑:Version2 正则表达式搜索 oneOfPossibleKeys=value
其中 value
结尾为:
, oneOfPossibleKeys=
- 或后面有字符串结尾(由
$
表示)。
代码:
String s = "type=INFO, languageCode=EN-GB, url=http://www.whosebug.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.whosebug.com
ref -> 1
info -> Text, that may contain all kind of chars.
deactivated -> false
我必须在这里处理一个由肮脏的设计引起的问题。我得到一个字符串列表,想从中解析属性。不幸的是,我无法更改创建这些字符串的来源。
示例:
String s = "type=INFO, languageCode=EN-GB, url=http://www.whosebug.com, ref=1, info=Text, that may contain all kind of chars., deactivated=false"
现在我想提取属性 type
、languageCode
、url
、ref
、info
和 deactivated
。
这里的问题是字段info
,其文本不受引号限制。此字段中也可能出现逗号,因此我不能在字符串末尾使用逗号来找出结束位置。
此外,这些字符串并不总是包含所有属性。 type
、info
和 deactivated
总是存在的,其余的是可选的。
有什么解决这个问题的建议吗?
一种可能的解决方案是在输入中搜索 =
个字符,然后将其前面的单个单词作为字段名称 - 似乎您所有的字段名称都是单个单词(无空格)。如果是这种情况,则可以将 =
之后直到下一个字段名称(用于分隔 ,
)的所有内容作为值。
这假定该值不能包含 =
。
编辑:
作为处理嵌入 =
的一种可能方法,您可以查看它前面的单词是否是您已知的字段名称 - 如果不是,您可以将 =
视为一个嵌入字符而不是运算符。然而,这假设您有一组固定的已知字段(其中一些可能不会总是出现)。如果您知道字段名称区分大小写,则可能会放宽此假设。
您可以使用正则表达式,捕获所有 "fixed" 组并使用 info
的剩余部分。如果 info
部分包含 ,
或 =
字符,这甚至应该有效。这是一些简单的示例(使用 Python,但这应该不是问题...)。
>>> p = r"(type=[A-Z]+), (languageCode=[-A-Z]+), (url=[^,]+), (ref=\d), (info=.+?), (deactivated=(?:true|false))"
>>> s = "type=INFO, languageCode=EN-GB, url=http://www.whosebug.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.whosebug.com',
'ref=1',
'info=Text, that may contain all kind of chars, even deactivated=true.',
'deactivated=false')
如果这些元素中的任何一个是可选的,您可以在这些组之后放置一个 ?
,并将逗号设为可选。如果顺序可以不同,那就更复杂了。在这种情况下,不是使用一个 RegEx 一次捕获所有内容,而是使用多个 RegEx 捕获各个属性,然后在匹配下一个属性之前删除(替换为 ''
)字符串中的那些属性。最后,匹配 info
.
进一步考虑,考虑到这些属性可以有任何顺序,更有希望捕获从一个关键字到下一个关键字的所有内容,而不考虑其实际内容,这与 Pshemo 的解决方案非常相似:
keys = "type|languageCode|url|ref|info|deactivated"
p = r"({0})=(.+?)(?=\, (?:{0})=|$)".format(keys)
matches = re.findall(p, s)
但这也可能在一些非常模糊的情况下失败,例如如果 info
属性包含类似 ', ref=foo'
的内容,包括逗号。然而,似乎没有办法解决这些歧义。如果你有一个像 info=in this string, ref=1, and in another, ref=2, ref=1
这样的字符串,它包含一个 ref
属性,还是三个,或者根本不包含 none?
假设元素的顺序是固定的,您可以像这样使用正则表达式编写解决方案
String s = "type=INFO, languageCode=EN-GB, url=http://www.whosebug.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.whosebug.com
rel -> 1
info -> Text, that may contain all kind of chars.
deactivated -> false
编辑:Version2 正则表达式搜索 oneOfPossibleKeys=value
其中 value
结尾为:
, oneOfPossibleKeys=
- 或后面有字符串结尾(由
$
表示)。
代码:
String s = "type=INFO, languageCode=EN-GB, url=http://www.whosebug.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.whosebug.com
ref -> 1
info -> Text, that may contain all kind of chars.
deactivated -> false