2012-08-02 59 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\/?\??$) 

到底。