2012-08-02 61 views
3

我想了解有关正则表达式的内容。
这里是我要匹配:正则表达式:查询字符串参数匹配

/parent/child 
/parent/child? 
/parent/child?firstparam=abc123 
/parent/child?secondparam=def456 
/parent/child?firstparam=abc123&secondparam=def456 
/parent/child?secondparam=def456&firstparam=abc123 
/parent/child?thirdparam=ghi789&secondparam=def456&firstparam=abc123 
/parent/child?secondparam=def456&firstparam=abc123&thirdparam=ghi789 
/parent/child?thirdparam=ghi789 
/parent/child/ 
/parent/child/? 
/parent/child/?firstparam=abc123 
/parent/child/?secondparam=def456 
/parent/child/?firstparam=abc123&secondparam=def456 
/parent/child/?secondparam=def456&firstparam=abc123 
/parent/child/?thirdparam=ghi789&secondparam=def456&firstparam=abc123 
/parent/child/?secondparam=def456&firstparam=abc123&thirdparam=ghi789 
/parent/child/?thirdparam=ghi789 

我的表情应该 “待价而沽” ABC123def456
而现在只是什么我不打算匹配的例子(“问号”丢失):

/parent/child/firstparam=abc123&secondparam=def456 

好吧,我建立了下面的表达式:

^(?:/parent/child){1}(?:^(?:/\?|\?)+(?:firstparam=([^&]*)|secondparam=([^&]*)|[^&]*)?)? 

但是,没有按没有工作。
你能帮我理解我做错了什么吗?
在此先感谢。

更新1

好吧,我做其他检查。 我想用这样的修复以前版本:

/parent/child(?:(?:\?|/\?)+(?:firstparam=([^&]*)|secondparam=([^&]*)|[^&]*)?)?$ 

让我解释一下我的想法:
必须与/父母/子女开始:

/parent/child 

下面的一组是可选的

(?: ...)? 

上一个可选组必须以?开头?要么 /?

(?:\?|/\?)+ 

可选参数(I抢值如果指定的参数是查询字符串的一部分)线

$ 

任何建议的

(?:firstparam=([^&]*)|secondparam=([^&]*)|[^&]*)? 

结束?

更新2

我的解决方案必须基于刚上正则表达式。 就比如,我以前写了下面的一个:

/parent/child(?:[?&/]*(?:firstparam=([^&]*)|secondparam=([^&]*)|[^&]*))*$ 

这工作相当不错。 但它下面的输入也很相配:

/parent/child/firstparam=abc123&secondparam=def456 

我怎么能修改表达式以以前的字符串相匹配?

+0

这是你所有可能的输入吗?它总是有这样的结构吗? – FailedDev 2012-08-02 08:20:24

+0

@FailedDev 是的。 – NicolaBaldi 2012-08-02 08:46:10

+0

@NicolaBaldi看到我的答案。不要为此使用正则表达式,导致类似你的任务可以(并且必须)通过简单的字符串处理函数来解决;)正则表达式是昂贵的工具,真的! – gaussblurinc 2012-08-02 10:32:02

回答

2

你没有指定一种语言,所以我只会使用Perl。所以基本上不是匹配所有东西,而是恰好匹配我认为你需要的东西。请纠正我,如果我错了。

while ($subject =~ m/(?<==)\w+?(?=&|\W|$)/g) { 
    # matched text = $& 
} 

(?<=  # Assert that the regex below can be matched, with the match ending at this position (positive lookbehind) 
    =  # Match the character “=” literally 
) 
\\w   # Match a single character that is a “word character” (letters, digits, and underscores) 
    +?  # Between one and unlimited times, as few times as possible, expanding as needed (lazy) 
(?=   # Assert that the regex below can be matched, starting at this position (positive lookahead) 
      # Match either the regular expression below (attempting the next alternative only if this one fails) 
     &  # Match the character “&” literally 
    |  # Or match regular expression number 2 below (attempting the next alternative only if this one fails) 
     \\W # Match a single character that is a “non-word character” 
    |  # Or match regular expression number 3 below (the entire group fails if this one fails to match) 
     \$ # Assert position at the end of the string (or before the line break at the end of the string, if any) 
) 

输出:

Results

+0

感谢FailedDev,但我使用的是.NET Framework的正则表达式引擎。 Perl语法对我来说根本不清楚。 :-( 无论如何,我很好奇我的模式有什么问题 – NicolaBaldi 2012-08-02 08:42:50

+0

这个正则表达式的语法从lang更改为lang吗? – mmdemirbas 2012-08-02 09:01:01

+0

@NicolaBaldi您可以将正则表达式部分插入.net。它支持我所拥有的written。 – FailedDev 2012-08-02 12:11:46

0

我的解决办法:
/(?:\w+/)*(?:(?:\w+)?\?(?:\w+=\w+(?:&\w+=\w+)*)?|\w+|)

解释:
/(?:\w+/)*比赛/parent/child//parent/

(?:\w+)?\?(?:\w+=\w+(?:&\w+=\w+)*)?比赛child?firstparam=abc123?firstparam=abc123?

\w+匹配文本像child

..|)比赛没有(空)

如果您只需要查询字符串,模式会降低,如:
/(?:\w+/)*(?:\w+)?\?(\w+=\w+(?:&\w+=\w+)*)

如果您想从查询中获取每个参数字符串,这是一个Ruby样本:

re = /\/(?:\w+\/)*(?:\w+)?\?(\w+=\w+(?:&\w+=\w+)*)/ 
s = '/parent/child?secondparam=def456&firstparam=abc123&thirdparam=ghi789' 
if m = s.match(re) 
    query_str = m[1] # now, you can 100% trust this string 
    query_str.scan(/(\w+)=(\w+)/) do |param,value| #grab parameter 
     printf("%s, %s\n", param, value) 
    end 
end 

输出

secondparam, def456 
firstparam, abc123 
thirdparam, ghi789 
+0

谢谢godspeedlee。您的解决方案可以帮助我很多,但它仍然过于通用,不会获取参数值。请看看我最近的更新。 – NicolaBaldi 2012-08-02 09:35:42

+0

我的解决方案必须基于正则表达式。参见更新2.我认为我几乎是正确的(希望!)。 – NicolaBaldi 2012-08-02 11:40:08

0

你不是在你的正则表达式对于初学者逃避/ S和使用{1}的东西单一重复是不必要的;你只在需要多次重复或重复范围时才使用它们。

而你想要做的一部分,根本不是一个正则表达式的好用。我会告诉你一个更简单的方法来处理这个问题:你想使用诸如split之类的东西,并将信息放入哈希中,以便稍后检查内容。因为你没有指定一种语言,所以我只是将Perl用于我的示例,但是我用正则表达式所了解的每种语言也可以轻松访问散列和类似于split的内容,所以这应该很容易进行移植:

# I picked an example to show how this works. 
my $route = '/parent/child/?first=123&second=345&third=678'; 
my %params; # I'm going to put those URL parameters in this hash. 

# Perl has a way to let me avoid escaping the /s, but I wanted an example that 
# works in other languages too. 
if ($route =~ m/\/parent\/child\/\?(.*)/) { # Use the regex for this part 
    print "Matched route.\n"; 
    # But NOT for this part. 
    my $query = $1; # $1 is a Perl thing. It contains what (.*) matched above. 
    my @items = split '&', $query; # Each item is something like param=123 
    foreach my $item (@items) { 
    my ($param, $value) = split '=', $item; 
    $params{$param} = $value; # Put the parameters in a hash for easy access. 
    print "$param set to $value \n"; 
    } 
} 

# Now you can check the parameter values and do whatever you need to with them. 
# And you can add new parameters whenever you want, etc. 
if ($params{'first'} eq '123') { 
    # Do whatever 
} 
0

此脚本将帮助您。
首先,我检查是否有像?这样的符号。
然后,我杀死了第一部分行(从?离开)。
接下来,我分割线&,其中每个值分裂=

my $r = q"/parent/child 
/parent/child? 
/parent/child?firstparam=abc123 
/parent/child?secondparam=def456 
/parent/child?firstparam=abc123&secondparam=def456 
/parent/child?secondparam=def456&firstparam=abc123 
/parent/child?thirdparam=ghi789&secondparam=def456&firstparam=abc123 
/parent/child?secondparam=def456&firstparam=abc123&thirdparam=ghi789 
/parent/child?thirdparam=ghi789 
/parent/child/ 
/parent/child/? 
/parent/child/?firstparam=abc123 
/parent/child/?secondparam=def456 
/parent/child/?firstparam=abc123&secondparam=def456 
/parent/child/?secondparam=def456&firstparam=abc123 
/parent/child/?thirdparam=ghi789&secondparam=def456&firstparam=abc123 
/parent/child/?secondparam=def456&firstparam=abc123&thirdparam=ghi789 
/parent/child/?thirdparam=ghi789"; 


for my $string(split /\n/, $r){ 
     if (index($string,'?')!=-1){ 
      substr($string, 0, index($string,'?')+1,""); 
      #say "string = ".$string; 
      if (index($string,'=')!=-1){ 
       my @params = map{$_ = [split /=/, $_];}split/\&/, $string; 
       $"="\n"; 
       say "$_->[0] === $_->[1]" for (@params); 
       say "######next########"; 
       } 
      else{ 
       #print "there is no params!" 
      }  

     } 
     else{ 
      #say "there is no params!"; 
     }  
    } 
1

只要你知道你的参数名称将会是什么并且你确定它们不会改变,这个正则表达式就会工作。

\/parent\/child\/?\?(?:(?:firstparam|secondparam|thirdparam)\=([\w]+)&?)(?:(?:firstparam|secondparam|thirdparam)\=([\w]+)&?)?(?:(?:firstparam|secondparam|thirdparam)\=([\w]+)&?)? 

虽然正则表达式是不是我们的最佳解决方案(上面的代码示例将更有效,因为字符串函数比正则表达式的方法快),如果你需要一个正则表达式的解决方案多达这将工作3个参数。出于兴趣,为什么解决方案只能使用正则表达式?

在任何情况下,这个正则表达式将匹配以下字符串:

/parent/child?firstparam=abc123 
/parent/child?secondparam=def456 
/parent/child?firstparam=abc123&secondparam=def456 
/parent/child?secondparam=def456&firstparam=abc123 
/parent/child?thirdparam=ghi789&secondparam=def456&firstparam=abc123 
/parent/child?secondparam=def456&firstparam=abc123&thirdparam=ghi789 
/parent/child?thirdparam=ghi789 
/parent/child/?firstparam=abc123 
/parent/child/?secondparam=def456 
/parent/child/?firstparam=abc123&secondparam=def456 
/parent/child/?secondparam=def456&firstparam=abc123 
/parent/child/?thirdparam=ghi789&secondparam=def456&firstparam=abc123 
/parent/child/?secondparam=def456&firstparam=abc123&thirdparam=ghi789 
/parent/child/?thirdparam=ghi789 

它现在只匹配那些包含查询字符串参数,并把它们放到捕获组你。

你用什么语言来处理你的比赛?

如果您使用的preg_match与PHP,你可以在阵列中的整场比赛,以及捕获组,

preg_match($regex, $string, $matches); 

然后你可以用$比赛[0],其余访问整个比赛与$匹配[1],$匹配[2]等。

如果您想添加额外的参数,您还需要将它们添加到正则表达式中,并添加额外的部件以获取您的数据。例如,如果你有

/parent/child/?secondparam=def456&firstparam=abc123&fourthparam=jkl01112&thirdparam=ghi789 

正则表达式将成为

\/parent\/child\/?\?(?:(?:firstparam|secondparam|thirdparam|fourthparam)\=([\w]+)&?)(?:(?:firstparam|secondparam|thirdparam|fourthparam)\=([\w]+)&?)?(?:(?:firstparam|secondparam|thirdparam|fourthparam)\=([\w]+)&?)?(?:(?:firstparam|secondparam|thirdparam|fourthparam)\=([\w]+)&?)? 

这将变得更有点乏味,以保持你增加更多的参数,虽然。

如果启用多行标志,您可以选择在开始和结束时包含^ $。如果您还需要匹配整个行没有查询字符串,包裹在非捕获组(包括^ $)这整个正则表达式,并添加

|(?:^\/parent\/child\/?\??$) 

到底。