3

URLに一致する素晴らしい仕事をする次の正規表現があります:

((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+[\w\d:#@%/;$()~_?\+-=\\\.&]*)`

ただし、プレフィックスのない URL は処理しません。stackoverflow.comまたはwww.google.comが一致しません。プレフィックスがあるかどうかを気にしないようにこの正規表現を変更する方法を知っている人はいますか?


編集: 私の質問があいまいすぎますか? 詳細が必要ですか?


(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\)))?[\w\d:#@%/;$()~_?\+-=\\\.&]*)

() を追加しましたか? Vinko Vrsalovicが提案したようなプロトコルの周りで、正規表現は、有効な URL 文字が含まれている限り、ほぼすべての文字列と一致するようになりました。

これの私の実装は、コンテンツを管理するデータベースがあり、プレーンテキスト、電話番号、URL、または電子メールアドレスのいずれかを持つフィールドがあります。入力を検証する簡単な方法を探していたので、適切にフォーマットすることができます。URL/電子メールのアンカー タグを作成し、サイト全体で他の番号をフォーマットする方法で電話番号をフォーマットします。助言がありますか?

4

5 に答える 5

2

以下の正規表現は、すばらしいMastering Regular Expressionsの本からのものです。フリー スペーシング/コメント モードに慣れていない場合は、慣れることをお勧めします。

\b
# Match the leading part (proto://hostname, or just hostname)
(
    # ftp://, http://, or https:// leading part
    (ftp|https?)://[-\w]+(\.\w[-\w]*)+
  |
    # or, try to find a hostname with our more specific sub-expression
    (?i: [a-z0-9] (?:[-a-z0-9]*[a-z0-9])? \. )+ # sub domains
    # Now ending .com, etc. For these, require lowercase
    (?-i: com\b
        | edu\b
        | biz\b
        | gov\b
        | in(?:t|fo)\b # .int or .info
        | mil\b
        | net\b
        | org\b
        | name\b
        | coop\b
        | aero\b
        | museum\b
        | [a-z][a-z]\b # two-letter country codes
    )
)

# Allow an optional port number
( : \d+ )?

# The rest of the URL is optional, and begins with / . . . 
(
     /
     # The rest are heuristics for what seems to work well
     [^.!,?;"'<>()\[\]{}\s\x7F-\xFF]*
     (?:
        [.!,?]+  [^.!,?;"'<>()\[\]{}\s\x7F-\xFF]+
     )*
)?

この正規表現を簡単に説明するには (完全な説明については本を入手してください) - URL には 1 つ以上のドットで区切られた部分があり、最後のビットの限定されたリストまたは 2 文字の国コード (.uk .fr ...) で終わります。さらに、パーツには任意の英数字またはハイフン「-」を含めることができますが、ハイフンをパーツの最初または最後の文字にすることはできません。次に、ポート番号があり、その後に残りがあります。

これを Web サイトから抽出するには、 http://regex.info/listing.cgi?ed= 3&p=207 にアクセスし てください。第 3 版の 207 ページからのものです。

また、そのページには「Copyright © 2008 Jeffrey Friedl」と書かれているので、使用条件が正確にはわかりませんが、本を所有している場合は使用できると思います。ここに置いてルールを破らないでください。

于 2008-10-22T17:05:26.147 に答える
1

URL 仕様 ( http://www.isi.edu/in-notes/rfc1738.txt ) のセクション 5 を読むと、URL の構文が最小限であることがわかります。

scheme ':' schemepart

ここで、scheme は 1 文字以上で、schemepart は 0 文字以上です。したがって、コロンがない場合、URL はありません。

とは言っても、/users/ はあなたに URL を与えても気にしません。だからここに私がすることがあります:

検証の前に、コロンが含まれていない場合は、先頭に http:// を追加してから、必要なバリデーターを実行します。これにより、正当なホスト名 (ドメイン情報が含まれていない可能性があります) が URL のようなものに変換されます。

frob  ->  http://frob

(ほぼ) ホスト部分の唯一の規則は、ドットが含まれていない場合、数字で始めることはできないということです。現在、特定のスキームに対して実行する必要がある特定の検証がありますが、これまでに与えられた正規表現はどれも達成していません。しかし、仕様への準拠はおそらく「検証」したいものではありません。したがって、ホスト名部分の dns クエリが役立つ場合がありますが、ユーザーと同じコンテキストで同じリゾルバーを使用していない限り、すべての場合に機能するとは限りません。

于 2008-10-22T18:00:49.403 に答える
0

正規表現は、これらのプロトコルのいずれかで始まるすべてのものと一致します。これには、存在する可能性のある URL である可能性がない多くのものが含まれます。プロトコル部分を緩和すると (? でオプションにする)、空の文字列を含むほとんどすべてのものと一致します。 .

つまり、 http://、https://、ftp://などで始まるほとんどすべてのものに一致するため、URL の一致に優れた仕事をします。ftp:\\ と ms-help:// にも一致しますが、無視しましょう。

有効なドメインをホワイトリストに登録する他の正規表現アプローチはすぐに保守できなくなるため、実際の使用状況によっては意味があるかもしれませんが、プロトコル部分をオプションにすることは意味がありません。

例 (緩和されたプロトコル部分を配置):

>>> r = re.compile('(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+)?[\w\d:#@%/;$()~_?\+-=\\\.&]*)')
>>> r.search('oompaloompa_is_not_an_ur%&%%l').groups()[0]
'oompaloompa_is_not_an_ur%&%%l' #Matches!
>>> r.search('oompaloompa_isdfjakojfsdi.sdnioknfsdjknfsdjk.fsdnjkfnsdjknfsdjk').groups()[0]
'oompaloompa_isdfjakojfsdi.sdnioknfsdjknfsdjk.fsdnjkfnsdjknfsdjk' #Matches!
>>>                             

あなたの編集を考慮して、有効な文字とおそらくいくつかの共通ドメインに加えて、ユーザーに追加するものを選択させるか、列挙型列を追加するか、少なくともドットをチェックするより単純な正規表現を作成することをお勧めします。

非常に遅く、URL 検証が本当に重要である場合にのみ使用される 3 番目の代替手段は、実際に URL にアクセスし、それに対して HEAD リクエストを実行することです。メールの場合、MX ホストが存在し、ポート 25 が開いているかどうかを試してみることができます。どちらも失敗した場合は、プレーン テキストになります。(これも推奨しているわけではありません)

于 2008-10-22T16:28:26.143 に答える
0

プレフィックス部分を括弧で囲み、0 または 1 回の出現に一致させることができます

(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+)?

したがって、正規表現全体は次のようになります

(((https?|ftp|gopher|telnet|file|notes|ms-help):((//)|(\\\\))+)?[\w\d:#@%/;$()~_?\+-=\\\.&]*)

それに関する問題は、多かれ少なかれ任意の単語に一致することです。たとえば、「test」も一致します。

その正規表現をどこで使用しますか? ホスト名を検証しようとしていますか、それとも段落内でホスト名を見つけようとしていますか?

于 2008-10-22T16:39:56.697 に答える
-2

使用するだけです:

.*

つまり、すべてに一致します。

一致させたいのは、URLではなくホスト名だけです(技術的に)。

ホスト名を明確に識別するために使用できる構造はありません。おそらく、「。com」で終わるものを探すことはできますが、.co.uk、net、.orgなどを見逃すことになります。

編集:

言い換えると、URLのようなものがプロトコルで始まるという要件を削除すると、一致するものがなくなります。正規表現を使用しているものに応じて、次のようになります。

  1. すべてをURLとして扱います
  2. プロトコルの要件を維持する
  3. ホスト名(.com .net .orgなど)の一般的な末尾をハックチェックし、一部を見逃すことを受け入れます。
于 2008-10-22T16:23:54.077 に答える