2016-03-12 21 views
2

我想使正則表達式捕獲命令標誌和值。因此,例如,考慮到字符串:捕獲命令標誌和值的正則表達式

helloworld --name=stretch --message="Hi there everyone"

應該抓住namestretch,然後messageHi there everyone

所以我幾乎得到了我所需要的:

\--([a-zA-Z]+)=[\"\']*([^\"\s\'\\]*(?:\\.[^\\\'\"]*)*)\g

但我有與空間問題...如果我把它拿出來,它只能引用值正常工作,並它在它僅適用於不帶引號的字符串大聲笑...

這裏的regex101: https://regex101.com/r/eE1zP6/2

+0

有沒有逃脫引號字符串內的報價的可能性?如果不是,我想' - ([a-zA-Z] +)=([^「's] + |」[^「] *」|'[^'] *')'應該這樣做。 –

+0

是的,我試圖讓它接受逃脫報價 –

+0

對不起,但你怎麼逃脫報價? –

回答

2

而是用引號雜耍的,採取遠遠優於APPR oach:使用條件正則表達式。
基本格式如下:

(?(1)foo|bar) 
# Meaning: if group1 is set, use foo, otherwise bar as subpattern 

您的要求,這可以歸結爲:

--(?P<key>\w+)=(")?(?P<value>(?(2)[^"]+|[^\s]+)) 

PHP代碼,並解釋,這看起來更美麗:

<?php 
$string = 'helloworld --name=stretch --message="Hi there everyone"'; 
$regex = '~ 
      --(?P<key>\w+)=   # look for two dashes, capture every word character into the group "key" 
      (")?     # look for double quotes and make the group (2) optional 
      (?P<value>    # save the following to the group "value" 
       (?(2)[^"]+|[^\s]+) # if (2) is set, capture everything BUT a double quote 
            # else capture everything but a space (not allowed without quotes) 
      ) 
      ~x';     # verbose modifier 
preg_match_all($regex, $string, $matches, PREG_SET_ORDER); 
foreach ($matches as $match) 
    echo "Key: {$match['key']}, Value: {$match['value']}\n"; 
/* output: 
Key: name, Value: stretch 
Key: message, Value: Hi there everyone 
*/  
?> 

看到這個演示ideone.com

你甚至可以更進一步,允許單引號作爲分隔符,並有逃脫報價在你的價值觀像這樣:

--(?P<key>\w+)= 
(['"])?     # allow single or double quotes 
(?P<value>  
    (?(2).+?(?<!\\)(?=\2) # if (2) is set, match everything lazily afterwards 
          # and make sure that what follows is the formerly captured quote 
          # make also sure that what precedes, is not a backslash (thus allowing escaped quotes) 
    |[^\s]+) 
) 

看到這個demo on regex101.com(從@SebastianProske劫持,對不起隊友: )。

+0

this沒有考慮到單引號和逃脫報價(雖然我喜歡這種方法) –

+0

@SebastianProske:看看最新的答案在底部,你的例子改變了它(劫持它):) – Jan

+1

多走幾步,但看起來更漂亮 - 所以我會讓我的回答保持並upvote你的 –

3

如果它是合適的,你可以捕捉在differen的報價,不帶引號的消息T基團:

--(\w+)=(?:[\"\']([^\"\'\\]*(?:\\.[^\\\'\"]*)*)[\"\']|(\w+)) 

然後在你的代碼,你可以檢查它是否是一個引用(第2組)或加引號(第3組)。

+0

我也需要它來接受轉義報價Lol –

+0

@Stretch您可以編輯您的問題以包含該要求嗎? – jehna1

+0

這是在我的第一個正則表達式...但是沒關係 –

1

我的做法是以下幾點:

--([a-zA-Z]+)=([^"'\s]+|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*') 

開始很簡單:--([a-zA-Z]+)=匹配雙-其次是字母和=,捕捉的字母一組。 然後我們有3個替代品,沒有引號就是[^"'\s]+匹配所有不是引用或空格的東西(如果允許在值內允許刪除引號,"(?:[^"\\]|\\.)*"正在尋找雙引號,後面跟着任何數量的非雙引號或\後面跟着任何東西,直到有一個雙引號不被0123'所使用。'(?:[^'\\]|\\.)*'對單引號的做法是一樣的,這就允許(在我看來是正確的)混合引號,如我的例子的最後一行所示。

https://regex101.com/r/gE1hG6/2

+0

加一個劫持你的正則表達式的例子:) – Jan

0

如果不使用IF條件匹配,你可以嘗試:

--(\w+)=(?:('|")(.*?)(?<!\\)\2|(\S+)) 

DEMO HERE

+0

'('|「)'和'['」]'一樣,'\ S +'和'[^ \ s] +完全一樣。 '此外,這種方法需要更多的步驟(因爲'。*?')。 – Jan