1

URL の検証に正規表現を使用しています。この式は JavaScript では非常にうまく機能しますが、PHP ではこのエラーが発生します

A PHP Error was encountered

Severity: Warning

Message: preg_match() [function.preg-match]: Unknown modifier '('

Filename: home/auth.php

Line Number: 1596
A PHP Error was encountered

Severity: Warning

Message: preg_match() [function.preg-match]: Unknown modifier '('

Filename: home/auth.php

Line Number: 1601

これが私の表現です

$pattern ="/^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*(\.){1}((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/";

これはphp関数です

public function valid_url($data)
{
    $data = trim($data);

    if(!$data)
    {
        return TRUE;            
    }

    $pattern ="/^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+(\:[a-zA-Z0-9\.&%\$\-]+)*@)*(\.){1}((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/";
    $valid = preg_match($pattern,$data);

    if(!$valid)
    {
        $data = "http://".$data;
        $valid = preg_match($pattern,$data);
    }

    if(!$valid)
    {
        $this->form_validation->set_message('valid_url', 'Please enter a valid URL.');
        return FALSE;           
    }
    else
    {
        return TRUE;
    }       
}

私は正規表現が苦手なので、問題を理解できませんでした。正規表現の修正を手伝ってください。

4

3 に答える 3

6

うわー、それは大きな表現です。いくつかの欠点を見つけました。できれば説明したいと思います。それを分解しましょう:

$pattern ="/

ここが最初の間違いでした。スラッシュは URL の複数のセクションで使用されるため、別の区切り文字を使用する必要があります。~これは URL ではあまり使用されないため、チルダをお勧めします。これは、どこでもスラッシュをエスケープし続ける必要がないことを意味します\/

^(http|https|ftp)\:\/\/www\.([a-zA-Z0-9\.\-]+

この文字クラスには次のエラーが含まれています。文字クラス内では、ドットは単にドットを意味します。逃げる必要はありません。さらに、ダッシュを最後に配置すると、範囲を意味する可能性がないため、エスケープする必要もありません。文字クラスは短縮して になり[a-zA-Z0-9.-]+ます。

(\:[a-zA-Z0-9\.&%\$\-]+

ここ&で、文字クラス内に次のエラーがあります。これは、& だけでなく、&、a、m、または ; にも一致します。html コードに変換する必要はありません。変換すると、コードに含まれる任意の文字と一致することになります。そして、以前の知識を使用すると、ドットまたはダッシュが最後にある場合はエスケープする必要はありません。文字クラスではドル記号を意味するだけなので、ドル記号をエスケープする必要もありません。文字クラス内では、すべてのメタ文字はキャレット^、バックスラッシュ\、閉じ角括弧]、ダッシュ-(ただし、これが最後にある場合は残すことができます)、および区切り文字として選択したものを除くすべての標準文字です。チルダ~. この文字クラスは、 になり[a-zA-Z0-9.&%$-]+ます。

)*@)*(\.){1}

これの一部はエラーかもしれませんが、そうではないかもしれません。基本的に、ここでドットをキャプチャする必要はありますか? キャプチャする必要がない場合は、ブラケットをそのままにしておきます。ただし、繰り返しには明確なエラーがあります。{1}完全にそして全く余計なものです。そこにあるものはすべて、少なくとも 1 回は繰り返さなければなりません。これはコードを乱雑にするだけです。上記は、 に短縮でき)*@)*\.ます。

((25[0-5]|2[0-4][0-9]|[0-1]{1}

繰り返しますが、{1}は必要ありません。それを削除し((25[0-5]|2[0-4][0-9]|[0-1]ます。

[0-9]{2}|[1-9]{1}[0-9]{1}

そして再び2回、これは になり[0-9]{2}|[1-9][0-9]ます。
これを続ければ、次のコード ブロックを短縮できます。

|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])

の中へ

|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])

驚くほど良くなるわけではありませんが、少しでも役に立ちます。次:

|([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+

2 つの文字クラスを最適化できます|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+

\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2})

これは非常に制限的ですが、何らかの理由でこのようになっていると思いますので、そのままにしておきます。

)(\:[0-9]+)*(/

そして、ここにあなたのエラーの原因があります。スラッシュをエスケープしませんでした。ただし、別の区切り文字を使用するとこれが回避され、パターンが整理されるため、そのままにしておきます。

($|[a-zA-Z0-9\.\,\?\'\\\+&%\$#\=~_\-]+))*$/";

その文字クラスは、文字クラス内のすべてをエスケープする必要がないことがわかっているため、大幅に短縮できます。になることができ($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/";ます。

私たちが現在知っているすべてのものを使用して、パターンをより美しく、扱いやすくすることができます.

代わりに次のようになります。

$pattern = "~^(http|https|ftp)://www\.([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[0-9])|([a-zA-Z0-9-]+\.)+(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(/($|[a-zA-Z0-9.,?'\\+&%$#=\~_-]+))*$~";

式が小さくなったので、欠点を見つけたり、カスタマイズしたりするのが少し簡単になるはずです。

ちょっとしたメモ
ですが、いくつかのグループ化の先頭で次の構文を使用していることに気付きました(\:. コロンには必要ないので、バックスラッシュを削除しました。しかし、あなたはグループが捕らえられないようにしようとしていましたか? その場合、その構文は(?:.

編集::文字クラスを利用してパターンをさらに最適化することもできます

\d = [0-9]
\w = [a-zA-Z0-9_]

最後のパターン区切り文字の末尾に i を追加すると、大文字と小文字を区別しなくなります。つまり、書く代わりに、代わりに書く[a-zA-Z]ことができます[a-z]

またhttp|httpshttps?

したがって、パターンをさらに短縮することもできます。

$pattern = "~^(https?|ftp)://www\.([a-z\d.-]+(:[a-z\d.&%$-]+)*@)*((25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9])\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9]|0)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|[1-9]|0)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]\d|\d)|([a-z\d-]+\.)+(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-z]{2}))(:\d+)*(/($|[\w.,?'\\+&%$#=\~-]+))*$~i";
于 2012-04-24T12:09:30.157 に答える
1

エラーが1つあります。

[0-9]+)*(/($

[0-9]+)*(\/($

またはに

[0-9]+)*(($

エンダーであると想定されている場合、そうで/はないはずです。

しかし、真剣に、これを達成できる他の方法はありませんか?この文字列のトラブルシューティングは非常に困難です。

于 2012-04-24T11:35:49.380 に答える
0

標準の php 関数 filter_var を使用しないのはなぜですか?

http://lv.php.net/manual/ru/function.filter-var.php

于 2012-04-24T11:30:52.843 に答える