2

電話番号を携帯電話のリンクに変換するコードを作成しています。

import re
from string import digits

PHONE_RE = re.compile('([(]{0,1}[2-9]\d{2}[)]{0,1}[-_. ]{0,1}[2-9]\d{2}[-_. ]{0,1}\d{4})')

def numbers2links(s):
    result = ""
    last_match_index = 0
    for match in PHONE_RE.finditer(s):
          raw_number = match.group()
          number = ''.join(d for d in raw_number if d in digits)
          call = '<a href="tel:%s">%s</a>' % (number, raw_number)
          result += s[last_match_index:match.start()] + call
          last_match_index = match.end()
    result += s[last_match_index:]
    return result

>>> numbers2links("Ghost Busters at (555) 423-2368! How about this one: 555 456 7890! 555-456-7893 is where its at.")
'Ghost Busters at <a href="tel:5554232368">(555) 423-2368</a>! How about this one: <a href="tel:5554567890">555 456 7890</a>! <a href="tel:5554567893">555-456-7893</a> is where its at.'

とにかく、これをよりきれいにするために使用している正規表現または正規表現方法を再構築できますか?

アップデート

明確にするために、私の質問は私の正規表現の正しさについてではありません-それが限られていることを認識しています。代わりに、電話番号のリンクを代用する方法について誰かコメントがあったかどうか疑問に思っています-とにかくre.replace、私が持っている文字列ハッカーの代わりに使用できるものはありますか?

4

5 に答える 5

5

ナイスファーストテイク:) このバージョンはもう少し読みやすいと思います(そしておそらく少し速いです)。ここで注意すべき重要なことは、re.subの使用です。厄介な一致インデックスから私たちを遠ざけてくれます...

import re

PHONE_RE = re.compile('([(]{0,1}[2-9]\d{2}[)]{0,1}[-_. ]{0,1}[2-9]\d{2}[-_.  ]{0,1}\d{4})')
NON_NUMERIC = re.compile('\D')

def numbers2links(s):

   def makelink(mo):
      raw_number = mo.group()
      number = NON_NUMERIC.sub("", raw_number)
      return '<a href="tel:%s">%s</a>' % (number, raw_number)

   return PHONE_RE.sub(makelink, s)


print numbers2links("Ghost Busters at (555) 423-2368! How about this one: 555 456 7890! 555-456-7893 is where its at.")

注: 私の実践では、私が使用している 2 つのような単純な正規表現を何千回も使用している場合でも、プリコンパイルの速度が大幅に向上していることに気付きませんでした。re モジュールには、ある種の内部キャッシュがある可能性があります-わざわざソースを読んでチェックしませんでした。

string.digitsまた、各文字をチェックして別の文字が含まれているかどうかを確認する方法を置き換えました。これre.sub()は、私のバージョンの方が読みやすいと思うためであり、パフォーマンスが優れていると確信しているからではありません (そうなる可能性はありますが)。

于 2008-12-22T19:26:03.587 に答える
1

まず、1つの正規表現で電話番号を確実に取得することは困難であり、不可能になる傾向が強いことで有名です。すべての国が米国のように狭い「電話番号」の定義を持っているわけではありません。米国でも、物事は見た目よりも複雑です(北米番号計画に関するウィキペディアの記事から)。

  • A)国コード:オプションのプレフィックス(「1」または「+1」または「001」)
    • ((00|\+)?1)?
  • B)番号計画市外局番(NPA):1で始めることはできず、数字2を9にすることはできません
    • [2-9][0-8][0-9]
  • C)交換コード(NXX):1で開始することはできず、「11」で終了することはできません。オプションの括弧
    • \(?[2-9](00|[2-9]{2})\)?
  • D)駅コード:4桁、すべて0にすることはできません(私は推測します)
    • (?!0{4})\d{4}
  • E)オプションの拡張機能が続く場合があります
    • ([x#-]\d+)?
  • S)数字の一部は、スペース、ダッシュ、ドットで区切られています(またはされていません)。
    • [. -]?

したがって、米国の基本的な正規表現は次のようになります。

((00|\+)?1[. -]?)?\(?[2-9][0-8][0-9]\)?[. -]?[2-9](00|[2-9]{2})[. -]?(?!0{4})\d{4}([. -]?[x#-]\d+)?
| A       |S   |  |   B                | S   |   C             | S  |  D           | S  |  E      |

そして、それは米国の比較的些細な番号計画のためだけであり、そこでさえそれは確かにすべての微妙なことをカバーしているわけではありません。信頼性を高めたい場合は、予想されるすべての入力言語に対して同様の獣を開発する必要があります。

于 2008-12-22T09:41:01.817 に答える
1

正規表現は、国際標準ではない特定の形式のみを解析します。1 つの国に限定する場合は、うまくいく可能性があります。

それ以外の場合、国際標準はITU E.123 : 「国内および国際電話番号、電子メール アドレス、および Web アドレスの表記法」です。

于 2008-12-22T08:55:16.840 に答える
1

Why not re-use the work of others - for example, from RegExpLib.com?

My second suggestion is to remember there are other countries besides the USA, and quite a few of them have telephones ;-) Please don't forget us during your software development.

Also, there is a standard for the formatting of telephone numbers; the ITU's E.123. My recollection of the standard was that what it describes doesn't match well with popular usage.

Edit: I mixed up G.123 and E.123. Oops. Props Bortzmeyer

于 2008-12-22T06:37:28.287 に答える
0

機能を実際に変更することなく、既存の正規表現をクリーンアップするいくつかのこと:

{0,1} を ? に、[(] を (, [)] ) に置き換えます。[2-9] bea を \d にすることもできます。そのため、これらのパターンを最後の部分で \d{3} および \d{4} にすることができます。偽陽性率が実際に増加するとは思えません。

于 2008-12-22T05:57:05.917 に答える