سؤال

أنا أعمل قطعة من التعليمات البرمجية لتحويل أرقام الهواتف إلى روابط للهاتف المحمول - لقد حصلت عليه ولكن يبدو أن القذرة حقا.

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

هل هناك على أي حال يمكنني إعادة هيكلة Regex أو طريقة Regex التي أستخدمها لجعل هذا النظافة؟

تحديث

للتوضيح، سؤالي لا يتعلق بصلاحية Regex الخاص بي - أدرك أنه محدود. بدلا من ذلك، أتساءل ما إذا كان لدى أي شخص أي تعليقات على طريقة الرفض في روابط لأرقام الهواتف - هل هناك على أي حال يمكنني استخدامه re.replace أو شيء من هذا القبيل بدلا من اختراق السلسلة التي لدي؟

هل كانت مفيدة؟

المحلول

لطيفة أولا تأخذ :) أعتقد أن هذا الإصدار أكثر قابلية للقراءة قليلا (وربما بقليل بقليل). الشيء الرئيسي الذي يجب ملاحظته هنا هو استخدام 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.")

ملاحظة: في ممارستي، لم ألا لاحظت الكثير من التعبيرات العادية المسرعة مسبقا مثل الاثنين الذي أستخدمه، حتى لو كنت تستخدمهم الآلاف من المرات. قد يكون لدى الوحدة النمطية نوعا من التخزين المؤقت الداخلي - لم تهتم بقراءة المصدر والتحقق منها.

أيضا، استبدلت طريقك في التحقق من كل حرف لمعرفة ما إذا كان ذلك string.digits مع آخر re.sub() لأنني أعتقد أن إصداري هو أكثر قابلية للقراءة، وليس لأنني متأكد من أنه يعمل بشكل أفضل (على الرغم من أنه قد).

نصائح أخرى

يوزع Regexp الخاص بك فقط تنسيق محدد، وهو ليس المعيار الدولي. إذا قمت بحد نفسك إلى بلد واحد، فقد يعمل.

خلاف ذلك، المعايير الدولية هي الاتحاد E.123. : "تدوين أرقام الهواتف الوطنية والدولية وعناوين البريد الإلكتروني وعناوين الويب"

أولا قبالة، تلتقط أرقام الهواتف بشكل موثوق مع تعبير منتظم واحد أمر صعب للغاية مع ميل قوي لكونه مستحيلا. ليس كل بلد لديه تعريف "رقم هاتف" يضيق كما هو الحال في الولايات المتحدة حتى في الولايات المتحدة، والأشياء أكثر تعقيدا مما تبدو عليه (من مقال ويكيبيديا في خطة ترقيم أمريكا الشمالية):

  • أ) رمز البلد: بادئة اختيارية ("1" أو "+1" أو "001")
    • ((00|\+)?1)?
  • ب) ترقيم كود المنطقة (NPA): لا يمكن أن يبدأ مع 1، رقم 2 لا يمكن أن يكون 9
    • [2-9][0-8][0-9]
  • ج) رمز التبادل (NXX): لا يمكن أن يبدأ مع 1، لا يمكن أن ينتهي ب "11"، أقواس اختيارية
    • \(?[2-9](00|[2-9]{2})\)?
  • د) رمز المحطة: أربعة أرقام، لا يمكن أن يكون كل 0 (أفترض)
    • (?!0{4})\d{4}
  • ه) قد يتبع امتداد اختياري
    • ([x#-]\d+)?
  • S) أجزاء من الرقم مفصولة بالمسافات، شرطات، نقاط (أم لا)
    • [. -]?

لذلك، فإن Regex الأساسية بالنسبة للولايات المتحدة سيكون:

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

وهذا فقط لخطة الترقيم التافهة نسبيا للولايات المتحدة، وحتى هناك بالتأكيد لا يغطي جميع التفاصيل الدقيقة. إذا كنت ترغب في جعله موثوقا، فعليك تطوير وحش مماثل لجميع لغات الإدخال المتوقعة.

بعض الأشياء التي تنظف Regex الحالية دون تغيير الوظيفة:

استبدال {0،1} مع؟، [(] مع (، [)] مع). قد تجعلك أيضا ما عليك سوى جعلك [2-9] Bea D كذلك، حتى تتمكن من جعل هذه الأنماط تكون D {3} و d {4} للجزء الأخير. أشك في أنه سيزيد حقا من معدل الإيجابيات الخاطئة.

لماذا لا تستخدم عمل الآخرين - على سبيل المثال، من regexplib.com.?

اقتراحي الثاني هو أن نتذكر أن هناك بلدان أخرى إلى جانب الولايات المتحدة الأمريكية، وبعضها البعض لديه الهواتف ؛-) من فضلك لا تنسنا خلال تطوير البرمجيات الخاصة بك.

أيضا، هناك معيار لتنسيق أرقام الهواتف؛ الاتحاد الدولي للاتصالات E.123.. وبعد تذكرتي للمعيار هو أن ما يصفه لا يتطابق بشكل جيد مع الاستخدام الشعبي.

تحرير: اخترت G.123 و E.123. أووبس. الدعائم Bortzmeyer.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top