2013-05-01 20 views
3

使用Java和正则表达式,我想从一行文本中提取字符串。 的文本可以是在下面的格式 -使用Java和正则表达式分割复杂的字符串

  1. KEY1(值1)KEY2(值2)
  2. KEY1(值1)KEY2
  3. KEY1 KEY2(值2)
  4. KEY1 KEY2
  5. KEY1

当我使用空格分割文本,然后使用下面的模式提取关键字时,使用Type#1时,我能够成功地提取键和值小号

Pattern p = Pattern.compile("\\((.*?)\\)",Pattern.DOTALL); 

用于计数的次数“(”和与 空间occurence可用于例#2和情况#3匹配它一个复杂的代码的逻辑,但是,代码变得太长。当空间出现在值中时也会出现多重复杂化,因为这样会使文本分裂成为问题。

有没有更好的正则表达式split/holiding我可以用于上面描述的选择性案例?

+1

你assumin g键和值在它们中没有括号吗? – merlin2011 2013-05-01 17:32:25

+0

是@ merlin2011,他们的键和值本身没有括号。 – Prasoon 2013-05-01 17:47:33

回答

4

考虑下面的通用正则表达式的powershell示例。

(?<=^|[\s)\n])[\n]*([^(\n\s]*)([(]([^)\n]*)[)])?

$Matches = @() 
    $String = 'key1(value1) key2(value2) 
key3(value3) key3.5 
key4 key5(value5) GoofyStuff(I like kittens) 
key6 key7 ForReal-Things(be sure to vote) 
key8' 
    Write-Host start with 
    write-host $String 
    Write-Host 
    Write-Host found 
    ([regex]'(?<=^|[\s)\n])([^(\n\s]*)([(]([^)\n]*)[)])?').matches($String) | foreach { 
     if ($_.Groups[1].Value) { 
      write-host "key at $($_.Groups[1].Index) = '$($_.Groups[1].Value)'" 
      if ($_.Groups[3].Value) { 
       write-host "value at $($_.Groups[3].Index) = '$($_.Groups[3].Value)'" 
       } # end if 
      } # end if 
     } # next match 

息率
start with 
key1(value1) key2(value2) 
key3(value3) key3.5 
key4 key5(value5) GoofyStuff(I like kittens) 
key6 key7 ForReal-Things(be sure to vote) 
key8 

found 
key at 0 = 'key1' 
value at 5 = 'value1' 
key at 13 = 'key2' 
value at 18 = 'value2' 
key at 27 = 'key3' 
value at 32 = 'value3' 
key at 40 = 'key3.5' 
key at 48 = 'key4' 
key at 53 = 'key5' 
value at 58 = 'value5' 
key at 67 = 'GoofyStuff' 
value at 78 = 'I like kittens' 
key at 95 = 'key6' 
key at 100 = 'key7' 
key at 105 = 'ForReal-Things' 
value at 120 = 'be sure to vote' 
key at 138 = 'key8' 

摘要
  • (?<=^|[\s)\n]*)查找密钥的开始,每个键被假定为在字符串的开头,或在\ n之后,“(”或space - (?<=^|[\s)\n]*)这可能无法在Java中工作,因为Java处理带有未定义大小的lookaround时存在缺陷/功能。see also
  • (?<=^|[\s)\n])寻找一个关键的开始,每个键被假定为在字符串,或右后\ n“(”,或空间的开始 - (?<=^|[\s)\n])。这环顾四周,似乎在C#中的工作和PowerShell

  • ([^(\n\s]*)返回所有字符,直到下一个 “(” \ n或\ S如果存在

  • ([(]([^)\n]*)[)])?返回parans内的值

    循环中的额外的逻辑测试匹配阵列,以验证密钥名称和值被发现。在PowerShell中的$匹配自动从字符串所有匹配的项目填充。

+0

注意:此解决方案在C#中工作,但它目前依赖于Java的正则表达式实现中的错误/功能。 – nhahtdh 2013-05-01 18:35:50

+0

这是在PowerShell中编写和测试的,你能够扩展你所指的错误/功能吗? – 2013-05-01 18:49:53

+1

检查此问题:http://stackoverflow.com/questions/1536915/regex-look-behind-without-obvious-maximum-length-in-java Java正则表达式的“官方”文档是在模式类,它不' t真的很详细地描述了什么被认为对于后视无效。因此,不清楚这是一个错误还是一个功能。 – nhahtdh 2013-05-01 18:53:50

0

我的建议是:

Pattern p = Pattern.compile("(\\(?[^ \\n(]+\\)?)+"), Pattern.DOTALL); 

然后,迭代子匹配。如果第一个字符是paren,你就知道它是前一个键的值;否则,这是一个关键。如果这是一个值,只需使用substring即可剥离。

相关问题