我正在尝试使用正则表达式来捕获命令标志和值。例如,给定字符串:
helloworld --name=stretch --message="Hi there everyone"
它应该捕获name
和stretch
,然后message
和Hi there everyone
。
所以我几乎得到了我需要的东西:
\--([a-zA-Z]+)=[\"\']*([^\"\s\'\\]*(?:\\.[^\\\'\"]*)*)\g
但是我对这个空间有问题...如果我把它拿出来,它只适用于引用的值,并且在它中它只适用于不带引号的字符串Lol ......
这是regex101: https://regex101.com/r/eE1zP6/2
答案 0 :(得分:3)
如果它合适,您可以捕获不同组中的引用和不引用的消息:
--(\w+)=(?:[\"\']([^\"\'\\]*(?:\\.[^\\\'\"]*)*)[\"\']|(\w+))
然后在您的代码中,您可以检查它是引用的(第2组)还是不引用的(第3组)。
答案 1 :(得分:2)
不要使用引号,而是采用更优越的方法:使用条件正则表达式。
基本形式如下:
(?(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劫持,对不起伙伴:)。
答案 2 :(得分:1)
我的方法如下:
--([a-zA-Z]+)=([^"'\s]+|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')
开始很简单:--([a-zA-Z]+)=
匹配双-
后跟字母和=,捕获组中的字母。
然后我们有3个替代方案,没有引号,[^"'\s]+
匹配所有不是引号或空格的内容(如果允许在值内,则可以删除引号。"(?:[^"\\]|\\.)*"
正在寻找双引号后跟任何数量的非双引号或\
后跟任何内容,直到\.
未使用双引号。'(?:[^'\\]|\\.)*'
对单引号执行相同的操作。 (在我看来是正确的)混合引号,如我的例子的最后一行所示。
答案 3 :(得分:0)