Regex: تطابق سلسلة تحتوي على أرقام وحروف ولكن ليس سلسلة من الأرقام فقط

StackOverflow https://stackoverflow.com/questions/1240674

سؤال

سؤال

أود أن أكون قادرا على استخدام Regex واحد (إذا كان ذلك ممكنا) أن تتطلب سلسلة تناسبها [A-Za-z0-9_] ولكن لا يسمح:

  • سلاسل تحتوي على أرقام أو / ورموز فقط.
  • سلاسل تبدأ أو تنتهي برموز
  • رموز متعددة بجانب بعضنا البعض

صالح

  • test_0123
  • t0e1s2t3
  • 0123_test
  • te0_s1t23
  • t_t

غير صالح

  • t__t
  • ____
  • 01230123
  • _0123
  • _test
  • _test123
  • test_
  • test123_

أسباب القواعد

الغرض من ذلك هو تصفية أسماء المستخدمين لموقع الويب الذي أعمل عليه. لقد وصلت إلى قواعد أسباب محددة.

  • أسماء المستخدمين مع الأرقام و / أو الرموز فقط قد تتسبب في مشاكل في البحث عن التوجيه وقاعدة البيانات. الطريق ل /users/#{id} يسمح id أن تكون إما معرف المستخدم أو اسم المستخدم. لذلك يجب ألا تكون الأسماء والمعرفات قادرة على التصادم.

  • _test يبدو غريب وأنا لا أصدق أنه فرعي صالح IE _test.example.com

  • أنا لا أحب مظهر t__t كخارج. بمعنى آخر t__t.example.com

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

المحلول

هذا يطابق بالضبط ما تريد:

/\A(?!_)(?:[a-z0-9]_?)*[a-z](?:_?[a-z0-9])*(?<!_)\z/i
  1. شخصية أبجدية واحدة على الأقل ( [a-z] في المنتصف).
  2. لا يبدأ أو ينتهي مع الشرطة السفلية ( (?!_) و (?<!_) في البداية والنهاية).
  3. قد يكون لديك أي عدد من الأرقام أو الحروف أو السفلات السفلية قبل وبعد الطابع الأبجدي، ولكن يجب فصل كل سفن إبطال عن طريق رقم واحد أو حرف واحد على الأقل (الباقي).

تحرير: في الواقع، ربما لا تحتاج حتى إلى Lookahead / Lookbehinds بسبب كيفية عمل بقية Regex - الأول ?: الأقواس لن تسمح تحت السطر إلى ما بعد أبجدي رقمي، والثاني ?: Purenthetical لن تسمح بإشرار السفلات السطرية ما لم يكن قبل أبجدي رقمي:

/\A(?:[a-z0-9]_?)*[a-z](?:_?[a-z0-9])*\z/i

يجب أن تعمل بشكل جيد.

نصائح أخرى

أنا متأكد من أنك استطاع ضع كل هذا في تعبير واحد عادي، لكنه لن يكون بسيطا ولست متأكدا من السبب في الإصرار على كونه واحد regex. لماذا لا تستخدم تمريرات متعددة أثناء التحقق من الصحة؟ إذا تم إجراء عمليات التحقق من الصحة عند إنشاء المستخدمين حسابا جديدا، فلن يكون هناك أي سبب حقا لمحاولة الإسراع في Regex. (وهذا هو، سوف تتعامل فقط مع عنصر واحد في كل مرة، وليس المئات أو الآلاف أو أكثر. يجب أن يستغرق عدد قليل من الأمور على اسم مستخدم طبيعي الحجم القليل جدا، وأعتقد.)

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

ماذا عن:

/^(?=[^_])([A-Za-z0-9]+_?)*[A-Za-z](_?[A-Za-z0-9]+)*$/

لا يستخدم مرجعا مرة أخرى.

يحرر:

ينجح لجميع حالات الاختبار الخاصة بك. هو uby متوافق.

هذا لا يمنع "__"، لكنه يحصل على البقية:

([A-Za-z]|[0-9][0-9_]*)([A-Za-z0-9]|_[A-Za-z0-9])*

وهنا شكل أطول يحصل على كل قواعدك:

([A-Za-z]|([0-9]+(_[0-9]+)*([A-Za-z|_[A-Za-z])))([A-Za-z0-9]|_[A-Za-z0-9])*

دانغ، هذا قبيح. سوف أتفق مع Telemachus، ربما لا ينبغي أن تفعل هذا مع واحد Regex، على الرغم من أنه ممكن من الناحية الفنية. Regex غالبا ما يكون ألم للصيانة.

يسأل السؤال عن regexp واحد، ويعني أنه يجب أن يكون regexp ذلك اعواد الكبريت, ، وهذا ما يرام، والإجابة على الآخرين. من أجل الفائدة، ألا لاحظ أن هذه القواعد أسهل من الأسهل تماما كإحالة مثل RegExP ليس تطابق. بمعنى آخر:

x !~ /[^A-Za-z0-9_]|^_|_$|__|^\d+$/
  • لا توجد أحرف أخرى من الحروف والأرقام و _
  • لا يمكن أن تبدأ مع
  • لا يمكن أن ينتهي مع _
  • لا يمكن أن يكون اثنين _s على التوالي
  • لا يمكن أن يكون كل الأرقام

لا يمكنك استخدامه بهذه الطريقة في القضبان التحقق من صحة_format_of، ولكن يمكنك وضعه بطريقة صحيحة للفئة، وأعتقد أن لديك فرصة أفضل بكثير لا تزال قادرا على فهم ما تعنيه، شهريا أو سنة من الآن.

ها أنت ذا:

^(([a-zA-Z]([^a-zA-Z0-9]?[a-zA-Z0-9])*)|([0-9]([^a-zA-Z0-9]?[a-zA-Z0-9])*[a-zA-Z]+([^a-zA-Z0-9]?[a-zA-Z0-9])*))$

إذا كنت ترغب في تقييد الرموز التي تريد قبولها، فما عليك سوى تغيير الكل [^ a-za-z0-9] مع [] تحتوي على جميع الرموز المسموح بها

(?=.*[a-zA-Z].*)^[A-Za-z0-9](_?[A-Za-z0-9]+)*$

هذا يعمل.

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

/^(?![\d_]+$)[A-Za-z0-9]+(?:_[A-Za-z0-9]+)*$/

سؤالك هو في الأساس نفس هذا, مع الاحتياجات المضافة التي يجب أن تكون إحدى الأحرف على الأقل خطابا. Lookahead السلبي - (?![\d_]+$) - يعتني بهذا الجزء، وهو أسهل بكثير (كلاهما للقراءة والكتابة) من دمجها في Regex الأساسية كما حاول البعض الآخر القيام به.

[A-Za-z][A-Za-z0-9_]*[A-Za-z]

من شأنها أن تعمل في أول قاعديتين لديك (نظرا لأنها تتطلب خطابا في البداية والنهاية للقاعدة الثانية، فإنها تتطلب تلقائيا رسائل).

لست متأكدا من القاعدة الثالثة ممكنة باستخدام Regexes.

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