3

使用 Java 和正则表达式,我想从一行文本中提取字符串。文本可以采用以下格式 -

  1. 键1(值1) 键2(值2)
  2. 键1(值1)键2
  3. 键 1 键 2(值 2)
  4. 键1 键2
  5. 键1

当使用 Type #1 时,我能够成功提取键和值,我可以使用空格分割文本,然后使用以下模式提取键

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

用于计算“(”的出现并将其与空格的出现匹配的复杂代码逻辑可用于案例#2和案例#3,但是,代码变得太长了。当值中存在空格时会出现多种复杂情况也是因为那样,拆分文本就成了问题。

是否有更好的正则表达式拆分/保留可以用于上面描述的选择性案例?

4

2 回答 2

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、"(" 或空格 - 之后(?<=^|[\s)\n]*)这在 Java 中可能不起作用,因为在java 如何处理未定义大小的环视。另见
  • (?<=^|[\s)\n])查找键的开头,假定每个键位于字符串的开头,或者紧跟在 \n、"(" 或空格 - 之后(?<=^|[\s)\n])。这种环顾四周似乎在 C# 和 Powershell 中有效

  • ([^(\n\s]*)返回直到下一个 "("、\n 或 \s 之前的所有字符

  • ([(]([^)\n]*)[)])?如果存在,则返回参数内的值

    循环内的额外逻辑测试 Matches 数组以验证是否找到了键名或值。在 powershell 中,$Matches 会自动填充字符串中的所有匹配项。

于 2013-05-01T18:04:06.047 回答
0

我的建议是:

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

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

于 2013-05-01T17:39:30.267 回答