Search code examples
javascriptregexstringmatchunicode-escapes

Regex to accept only 5 numbers and then a dash or a letter on typescript


I am dealing with an issue with Regex. I have a input which has maxLength 10.

I achieved till now to have the first given value can be digits for example 12345 but then it waits for a dash and after it you can write a letter or again a number maxLength=10 for example: 12345-a121 is allowed and it works with the currrent

But I want to be possible after the 5 digits to be allowed letters or dash because for the moment with this regex it is allowed only dash after 5 digits. For example 12345a or 12345- to be allowed. This is the actual regex what I am using.

Valid/Matches: 12345a235, 123a, 12345-aa1, 12345a, 12345-a.  

Not Valid/Does not matches: -11, 111111, aaaa, 

(?=^[^W_]{1,5}-[^W_]{1,8}$)^.{1,10}$|^[^W_]{1,5}$

I am debugging on the regex101.com but I am not finding a way for that to allow. 12345a for example

This is the condition to check if it matches or not.

if (!this.value.toString().match('^\d{1,5}(?!\d+)[-\p{L}\d]+$') && this.value.toString()) {
      return ValidationInfo.errorCode("You need to do something");

Thank you for the help


Solution

  • Edit since the patterns of the first approach can be simplified and also were missing the limitations of the ending sequence's length.

    Example code ...

    const multilineSample = `12345a235
    123a
    12345-aa1
    12345a
    12345-a
    
    12-a235dkfsf
    12-a235dkfsfs
    
    123a-dssava-y
    123a-dssava-1a
    
    12345-aa1--asd-
    12345-aa1--asd-s
    
    -11
    111111
    aaaa`;
    
    // see ... [https://regex101.com/r/zPkcwv/3]
    const regXJustMatch = /^\d{1,5}[-\p{L}][-\p{L}\d]{0,9}$/gmu;
    
    // see ... [https://regex101.com/r/zPkcwv/4]
    const regXNamedGroups =
      /^(?<digitsOnly>\p{N}{1,5})(?<miscellaneous>[-\p{L}][-\p{L}\p{N}]{0,9})$/gmu;
    
    console.log(
      'matches only ...',
      multilineSample.match(regXJustMatch)
    );
    console.log(
      'matches and captures ...', [
        ...multilineSample.matchAll(regXNamedGroups)
      ]
      .map(({ 0: match, groups }) => ({ match, ...groups }))
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }


    1st approach

    For both variants it is obvious to start with ...

    • a digit sequence of at least 1 and up to 5 digits ...

    It's also clear, one wants to end with a character sequence of any of dash and/or word. Due to having to exclude _ one can not just use the \w escape for letters and digits since \w covers/includes _ as well. But one could use unicode property escapes, thus ...

    • a regex covering the end of a line with a valid character class is ...
      • already mixed ... [-\p{L}\d]+$
      • mostly unicode escapes ... [-\p{L}\p{N}]+)$

    A combined regex like ... /^\d{1,5}[-\p{L}\d]+$/u ... almost covers the requirements but fails for 111111 which of cause gets matched even though it shouldn't according to the requirements.

    A negative lookahead ... (?!\d+) respectively (?!\p{N}+) ... which follows the starting digit sequence does prevent any other (terminating) digit-only sequence, thus 123456 does not get matched anymore.

    Example code ...

    const multilineSample = `12345a235
    123a
    12345-aa1
    12345a
    12345-a
    
    -11
    111111
    aaaa`;
    
    // see ... [https://regex101.com/r/zPkcwv/1]
    const regXJustMatch = /^\d{1,5}(?!\d+)[-\p{L}\d]+$/gmu;
    
    // see ... [https://regex101.com/r/zPkcwv/2]
    const regXNamedGroups =
      /^(?<digitsOnly>\p{N}{1,5}(?!\p{N}+))(?<miscellaneous>[-\p{L}\p{N}]+)$/gmu;
    
    console.log(
      'matches only ...',
      multilineSample.match(regXJustMatch)
    );
    console.log(
      'matches and captures ...', [
        ...multilineSample.matchAll(regXNamedGroups)
      ]
      .map(({ 0: match, groups }) => ({ match, ...groups }))
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }