Frage

Ich arbeite ein Stück Code Telefonnummern in Links für Handy drehen -. Ich habe es aber es fühlt sich wirklich schmutzig

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.'

Gibt es trotzdem ich die Regex oder die regex Methode umstrukturieren könnte ich diese sauberer machen bin mit?

Aktualisieren

Um zu klären, meine Frage ist nicht über die Richtigkeit meiner regex - Ich weiß, dass es begrenzt ist. Stattdessen frage ich mich, wenn jemand irgendwelche Kommentare über die Methode des substiting in Links für die Telefonnummern hatte - ist es trotzdem, ich re.replace oder so ähnlich, dass anstelle der Zeichenfolge hackery verwenden könnte, die ich habe

?
War es hilfreich?

Lösung

Nizza erste Klappe :) Ich denke, diese Version etwas besser lesbar ist (und wahrscheinlich ein teensy etwas schneller). Der Schlüssel ist hier zu beachten, ist die Verwendung von re.sub . Hält uns weg von dem bösen Spiel Indizes ...

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.")

Ein Hinweis: In meiner Praxis habe ich viel von einer Beschleunigung vor-Kompilierung einfachen regulären Ausdrücken wie die beiden nicht bemerkt, ich verwende, auch wenn man sie tausende Male verwenden. Das re-Modul kann eine Art internen Caching hat -. Nicht die Mühe, um die Quelle zu lesen und prüfen

Auch ich ersetzt gewählter jedes Zeichen zu überprüfen, ob es mit einem anderen string.digits in re.sub() ist, weil ich meine Version denke mehr lesbar ist, nicht, weil ich sicher bin, es besser abschneidet (obwohl es könnte).

Andere Tipps

Ihr regexp parst nur ein bestimmtes Format, die nicht der internationale Standard ist. Wenn Sie sich auf ein Land beschränken, kann es funktionieren.

Ansonsten ist der internationale Standard ist ITU E.123 : „Notation für nationale und internationale Telefonnummern, E-Mail-Adressen und Web-Adressen "

Zunächst einmal, zuverlässig Telefonnummern mit einem einzigen regulären Ausdruck Erfassung ist notorisch schwierig, mit einer starken Tendenz unmöglich zu sein. Nicht jedes Land hat eine Definition einer „Telefonnummer“, die so schmal ist, wie es in den USA ist auch in den USA, sind die Dinge komplizierter als sie scheinen (von der Wikipedia-Artikel auf dem nordamerikanischen Nummerierungsplan):

  • A) Ländercode: optional Präfix ( "1" oder "+1" oder "001")
    • ((00|\+)?1)?
  • B) Nummerierungsplan Vorwahl (NPA): mit 1 nicht beginnen kann, Ziffer 2 nicht 9 sein
    • [2-9][0-8][0-9]
  • C) Wechselcode (NXX): kann nicht mit 1 beginnen, kann nicht mit "11" enden, optional Klammern
    • \(?[2-9](00|[2-9]{2})\)?
  • D) Haltestelle Code: vier Ziffern, können alle nicht 0 (nehme ich an)
    • (?!0{4})\d{4}
  • E) eine optionale Erweiterung können folgen
    • ([x#-]\d+)?
  • S) Teile der Zahl sind durch Leerzeichen, Bindestriche, Punkte (oder nicht getrennt)
    • [. -]?

So wäre die grundlegende Regex für die US-:

((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      |

Und das ist nur für den relativ trivial Nummerierungsplan der US-und auch dort sicher ist es nicht alle Feinheiten abdeckt. Wenn Sie es zuverlässig machen wollen, müssen Sie ein ähnliches Tier für alle erwarteten Eingabesprachen entwickeln.

Ein paar Dinge, die Ihren vorhandenen Regex sauber werden, ohne wirklich die Funktionalität zu ändern:

Ersetzen Sie

{0,1} mit?, [(] Mit ([)] mit). Vielleicht haben Sie auch genausogut Ihr [2-9] b e a \ d sowie machen, so können Sie diese Muster machen d werden \ {3} und \ d {4} für den letzten Teil. Ich bezweifle, dass es wirklich die Rate der Fehlalarme erhöhen.

Warum nicht wiederverwenden, die Arbeit von anderen - zum Beispiel von RegExpLib.com ?

Mein zweiter Vorschlag ist, gibt es andere Länder außer den USA zu erinnern, und nicht wenige von ihnen Telefone haben ;-) Bitte vergessen Sie nicht, uns bei der Software-Entwicklung.

Außerdem gibt es einen Standard für die Formatierung von Telefonnummern; Die ITU E.123 . Meine Erinnerung an die Norm war das, was es beschreibt nicht gut überein mit populären Gebrauch.

Edit: Ich gemischt G.123 und E.123. Hoppla. Props Bortzmeyer

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top