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 で始める必要があります:

/parent/child

次のグループはオプションです

(?: ... )?

前のオプション グループは ? で始まる必要があります。また /?

(?:\?|/\?)+

オプションのパラメーター (指定されたパラメーターがクエリ文字列の一部である場合、値を取得します)

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

行の終わり

$

何かアドバイス?

更新 2

私の解決策は、正規表現のみに基づいている必要があります。たとえば、以前に次のように書きました。

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

そして、それはかなりうまく機能します。ただし、次の入力にも一致します。

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

前の文字列と一致しないように式を変更するにはどうすればよいですか?

4

5 に答える 5

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 “&amp;” 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)
)

出力:

結果

于 2012-08-02T08:25:23.777 に答える
0

/手始めに、正規表現で s をエスケープしていません{1}。何かを 1 回繰り返して使用する必要はありません。複数の繰り返しまたは繰り返しの範囲が必要な場合にのみ使用します。

そして、あなたがやろうとしていることの一部は、単に正規表現をうまく使用していないことです. これに対処する簡単な方法を紹介します。split のようなものを使用して、後で内容を確認できるように情報をハッシュに入れます。言語を指定しなかったので、例として Perl を使用しますが、正規表現で知っているすべての言語は、ハッシュや分割などにも簡単にアクセスできるため、これは簡単に移植できるはずです。

 # 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
 }
于 2012-08-02T08:46:20.187 に答える
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
于 2012-08-02T08:42:40.087 に答える
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!";
        }       
    }
于 2012-08-02T10:30:58.497 に答える