2013-05-01 24 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即可剝離。

相關問題