2010-05-27 163 views
1

我需要一個正則表達式匹配這樣的事情,如何使用正則表達式的形式相匹配的東西「的東西=富」「東西」 =「東西」「更多的東西」

「文」 | 'text'| ... | 'text'(〜text)='text'| 'text'| ... | 'text'

我只是想把它分成兩部分,等號左邊的部分和右邊的部分。任何'文本'條目都可以在'字符'之間有'='。我正在考慮嘗試匹配偶數個,然後是a =,但我不確定如何匹配偶數的數據。另外請注意,我不知道每邊有多少個條目可以存在。幾個例子,

'51NL9637X33'| 'ISL6262ACRZ-T'| 'QFN'(〜51NL9637X33)='51NL9637X33'| 'ISL6262ACRZ-T'| 'INTERSIL'| 'QFN7SQ-HT1_P49'| '()'

應該摘錄, '51NL9637X33'| 'ISL6262ACRZ-T'| 'QFN'(〜51NL9637X33) 和, '51NL9637X33'| 'ISL6262ACRZ-T'| 'INTERSIL'| 'QFN7SQ-HT1_P49'| '()'

'227637'| 'SMTU2032_1'| 'SKT W/BAT'(〜227637)='227637'| 'SMTU2032_1'| 'RENATA'| 'SKT28_5X16_1-HT5_4_P2'| '()':SPECIAL_A ='BAT_CR2032',PART_NUM_A ='202649'

應該提取, '227637'| 'SMTU2032_1'| 'SKT W/BAT'(〜227637) 和, '227637'| 'SMTU2032_1'| 'RENATA'| 'SKT28_5X16_1-HT5_4_P2'| '()':SPECIAL_A ='BAT_CR2032',PART_NUM_A ='202649'

另請注意,第一節末尾的小蒂爾達位是可選的,所以我不能只是尋找那個。

+0

您的最後一個示例不符合您的規範:':SPECIAL_A'位於「text」區域或「(〜text)」區域之外。你的代碼應該做什麼? – 2010-05-27 07:02:15

回答

4

其實我根本不會使用正則表達式。假設你的語言有split操作,我會先被分割在|角色獲得的列表:

'51NL9637X33' 
'ISL6262ACRZ-T' 
'QFN'(~51NL9637X33) = '51NL9637X33' 
'ISL6262ACRZ-T' 
'INTERSIL' 
'QFN7SQ-HT1_P49' 
'()' 

然後我他們每個人的分裂在=字符拿到鑰匙和(可選)值:

'51NL9637X33'   <null> 
'ISL6262ACRZ-T'   <null> 
'QFN'(~51NL9637X33)  '51NL9637X33' 
'ISL6262ACRZ-T'   <null> 
'INTERSIL'    <null> 
'QFN7SQ-HT1_P49'  <null> 
'()'     <null> 

您還沒有指定爲什麼你認爲一個正則表達式是這個職位的合適的工具,但最現代的語言也有split能力和正則表達式不一定是答案的各種需求。

0

我同意paxdiablo的規定,根據您使用的語言,正則表達式可能不是最適合此任務的工具。

問題「我如何匹配偶數個字符?」有趣的是儘管如此,這裏是我怎麼會做你的情況:通過在當前位置尋找一個'

(?:'[^']*'|[^=])*(?==) 

這種表達你的入門的左邊部分匹配。如果它找到一個,它會向前運行到下一個',從而只匹配偶數個引號。如果它沒有找到',它會匹配任何不是等號的東西,然後確保匹配的字符串後面有一個等號。它工作是因爲正則表達式引擎從左向右評估OR構造。

您可以通過使用

((?:'[^']*'|[^=])*)=(.*) 

得到兩個捕獲組的左右兩部分,我建議http://gskinner.com/RegExr/用正則表達式修修補補。 =)

0

由於paxdiablo說,你幾乎肯定不想在這裏使用正則表達式。 split建議不錯;我自己可能會在這裏使用解析器—有很多結構可以利用。這裏的想法是,你正式地指定了你所擁有的語法,只有嚴格的。所以,舉例來說:field是由單引號包圍的非單引號字符序列; fields是由空格分隔的field的任意數量,|以及更多空格;一個tilde是由(~)包圍的非右括號字符;而exprfields,可選空白,可選tilde=,可選空白以及另一個fields。你如何表達這取決於你使用的語言。在Haskell,例如,使用秒差距庫,你寫的每一個解析器如下:

import Text.ParserCombinators.Parsec 

field :: Parser String 
field = between (char '\'') (char '\'') $ many (noneOf "'\n") 

tilde :: Parser String 
tilde = between (string "(~") (char ')') $ many (noneOf ")\n") 

fields :: Parser [String] 
fields = field `sepBy` (try $ spaces >> char '|' >> spaces) 

expr :: Parser ([String],Maybe String,[String]) 
expr = do left <- fields 
      spaces 
      opt <- optionMaybe tilde 
      spaces >> char '=' >> spaces 
      right <- fields 
      (char '\n' >> return()) <|> eof 
      return (left, opt, right) 

瞭解此代碼恰恰是如何工作並不重要;基本的想法是打破你正在解析的內容,用正式的規則表達它,並且把它從小的組件中恢復出來。對於這樣的事情來說,它比正則表達式要乾淨得多。


如果你真的一個正則表達式,在這裏你去(勉強測試):

^\s*('[^']*'((\s*\|\s*)'[^'\n]*')*)?(\(~[^)\n]*\))?\s*=\s*('[^']*'((\s*\|\s*)'[^'\n]*')*)?\s*$ 

明白爲什麼我推薦一個解析器?當我第一次寫這篇文章的時候,我至少得到了兩件事我選擇了(每個測試一個),並且可能還有別的東西。而且我沒有在你想要的地方插入捕捉組,因爲我不確定他們會去哪裏。現在是的,我可以通過插入評論等方式使其更具可讀性。畢竟,regexen有其用途!但重點是:這不是其中之一。堅持一些更好的東西。