使用正则表达式解析复杂的字符串

时间:2010-06-15 17:08:48

标签: java javascript xml regex parsing

我的正则表达式技巧不是很好,最近新的数据元素将我的解析器抛入循环

采取以下字符串

“+ USER = Bob Smith-GROUP = Admin + FUNCTION = Read / FUNCTION = Write”

之前我的正则表达式有以下内容:[+ \\ - /]

哪会把结果变成

USER = Bob Smith
GROUP =管理员
功能=读
功能=写
功能=阅读

但是现在我的值中包含破折号,导致输出错误

新字符串看起来像“+ USER = Bob Smith-GROUP = Admin + FUNCTION = Read / FUNCTION = Write / FUNCTION = Read-Write”

这给了我以下结果,并打破了key = value结构。

USER = Bob Smith
GROUP =管理员
功能=读
功能=写
功能=读

有人可以帮我制定一个有效的正则表达式来处理这个问题,或者指出一些关键/值示例。基本上我需要能够处理+ - /符号以获得组合。

4 个答案:

答案 0 :(得分:0)

你没有指定你正在使用的正则表达式引擎,但是如果你有前瞻/后看,这就有效。

它的前提是键只是大写的,而值不是 - 不确定这是否是一个有效的假设,但如果不是那么注意事情会变得复杂和混乱。

(?<=[+-\/])[A-Z]+=(?:(?![A-Z]+=)[^=])+(?=[+-\/]|$)


这是我尝试解释的问题(不确定这有多大意义):

(?x)         # enable regex comment mode
(?<=[+-\/])  # start with one of the delimiters, but excluded from match
[A-Z]+       # match one or more uppercase (for the key)
=            # match the equal sign

(?:          # start non-capturing group

  (?!          # start negative lookahead, to prevent keys matching
    [A-Z]+=      # a key and equals (since in negative lookahead, this is what we exclude)
  )            # end the negative lookahead
  [^=]         # match a character that's not =

)+           # end non-capturing group, match one or more times, until...

(?=[+-\/]|$) # next char must be delimiter or end of line for match to succeed


对于Java字符串 - &gt;正则表达式,反斜杠需要转义(如引号一样):

Pattern p = Pattern.compile("(?<=[+-\\/])[A-Z]+=(?:(?![A-Z]+=)[^=])+(?=[+-\\/]|$)");


如果需要捕获组,只需在适当的部分添加parens:

Pattern p = Pattern.compile("(?<=[+-\\/])([A-Z]+)=((?:(?![A-Z]+=)[^=])+(?=[+-\\/]|$))");


将其转换为换行符分隔文本的匹配部分就像......

Matcher m = p.Matcher( InputText );
StringBuffer Result = new StringBuffer("");

while ( m.find() )
{
   Result.append( m.Group() + "\n" );
}

答案 1 :(得分:0)

根据您的第二个示例,此正则表达式:(\w+)=([\w|-|\s]+)会返回以下结果:

USER=Bob Smith
GROUP=Admin
FUNCTION=Read
FUNCTION=Write
FUNCTION=Read-Write

括号为每个元素提供分组,因此每个匹配将包含两个组,第一个将包含= =(USER,GROUP,FUNCTION)之前的部分,第二个将具有值(Bob Smith,Admin,Read ,写,读写)

您还可以为这些组命名,如果这样可以更容易:

(?<funcrion>\w+)=(?<value>[\w|-|\s]+)  

或者,如果您不关心这些群组,您可以完全删除这些群体

\w+=[\w|-|\s]+

答案 2 :(得分:0)

另一个选择,如果你有一组有限的键,你可以匹配:

(?<=[+-\\/])(USER|GROUP|FUNCTION)=[^=]+(?=$|[+-\\/](?:USER|GROUP|FUNCTION))


在Java中,我可能会这样实现:

String Key = "USER|GROUP|FUNCTION" ;
String Delim = "[+-\\/]";
Pattern p = Pattern.compile("(?<="+Delim+")("+Key+")=[^=]+(?=$|"+Delim+"(?:"+Key+"))");

这依赖于,例如“Write”不是有效键(并且如果你可以强制键的情况为“write”或“WRITE”那么这意味着它将起作用。)


将其转换为换行符分隔文本的匹配部分就像......

Matcher m = p.Matcher( InputText );
StringBuffer Result = new StringBuffer("");

while ( m.find() )
{
   Result.append( m.Group() + "\n" );
}

答案 3 :(得分:0)

如果您使用可能出现在值中的字符来分隔字段,则会被搞砸。

假设您收到如下字符串:

one=a-two=b-three=c-d-four=e

这会解析吗?

one=a
two=b
three=c-d
four=e

或者应该解析这个?

one=a
two=b
three=c
d-four=e

你怎么知道的?你决定这个的基础是什么?