How to give Match in word with several alternatives?

Asked

Viewed 127 times

1

I’m trying to give match us type of input that there is, however, the word "datetime-local" is causing me trouble, because if it is "datetime" he also finds a match.

For my expression to be correct I need her to find from a string of char inserted only the words corresponding to it, ie to be true in the case of "datetime" the word inserted would need to be "datetime-local" and not only "datetime".

How can I correct this expression?

 const regExpTypes = new RegExp(
      "button$|color$|date$|datetime(-local)$|email$|file$|hidden$|image$|month$|password$|radio$|range$|reset$|search$|submit$|tel$|text$|time$|url$|week$"
);
    
console.log(regExpTypes.test("datetime"));

2 answers

3


When you use alternation (the character |), the regex will try the alternatives from left to right, until find one that fits.

In this case, if the input is the string datetime, regex cannot find the match the first 16 alternatives (including the fourth - datetime(-local)$ - looking for something that ends with datetime-local, and see that parentheses make no difference here).

In alternative 17 (time$) she finds a match, since this passage means "ends with time", and datetime matches this. That’s why your regex returns true for the string datetime.

Your solution worked because you added ^, then the alternative "begins with datetime-local" now gives match - and datetime no more match because you’ve changed time$ (ends with time) for ^time (begins with time).

But anyway, if you want to check if a string matches exactly one of the names that are in regex, you can change it to:

 const regExpTypes = new RegExp(
   "^(button|color|date|datetime-local|email|file|hidden|image|month|password|radio|range|reset|search|submit|tel|text|time|url|week)$"
 );
    
 console.log(regExpTypes.test("datetime")); // false
 console.log(regExpTypes.test("datetime-local")); // true

This regex has the markers ^ and $, which are respectively the beginning and end of the string. Then between them there is a toggle with all the alternatives that you want to capture.


Note that all the alternatives are in parentheses, because it makes a difference.
If I do, for example, ^button|color$, that means "start with button, or ends with color" - and if it starts with button, may even have more after; if it ends with color, may have more things before - see:

 const regExpTypes = /^button|color$/;

 console.log(regExpTypes.test("button")); // true
 console.log(regExpTypes.test("button123")); // true
 console.log(regExpTypes.test("color")); // true
 console.log(regExpTypes.test("123color")); // true

If I ever put ^(button|color)$, that means "string start", followed by button or color, followed by the end of the string. That is, the string can only have what is in the alternatives, no more characters, no less (see).

 const regExpTypes = /^(button|color)$/;

 console.log(regExpTypes.test("button")); // true
 console.log(regExpTypes.test("button123")); // false
 console.log(regExpTypes.test("color")); // true
 console.log(regExpTypes.test("123color")); // false

So if you want the string to be exactly one of the alternatives, use ^(alternativas)$.


You can simplify it a little bit more:

 const regExpTypes = new RegExp(
   "^(button|color|date(time-local)?|email|file|hidden|image|month|password|ra(dio|nge)|reset|search|submit|te(l|xt)|time|url|week)$"
 );
    
 console.log(regExpTypes.test("datetime")); // false
 console.log(regExpTypes.test("datetime-local")); // true

I made some modifications:

  • date(time-local)?: the stretch time-local is in parentheses, and the ? soon after make it optional. So this stretch takes date or datetime-local (but not datetime)
  • ra(dio|nge): picks up the strings radio or range
  • te(l|xt): picks up the strings tel or text

Regex-free

But for this case it might be simpler to have an array with valid alternatives, and then check if the string is in this array, using the method includes:

 const validos = ['button', 'color', 'date', 'datetime-local', 'email',
                 'file', 'hidden', 'image', 'month', 'password', 'radio',
                 'range', 'reset', 'search', 'submit', 'tel', 'text', 'time', 'url', 'week'];
    
 console.log(validos.includes("datetime")); // false
 console.log(validos.includes("datetime-local")); // true

0

The answer of Marconi I don’t like it, but I used the link cited by the same for testing purposes, and I came to the following conclusion that it works as follows:

button|color$|date$|^datetime-local|email$|file$|hidden$|image$|month$|password$|radio$|range$|reset$|search$|submit$|tel$|text$|^time|url$|week$

Where the words datetime-local and time, shall use the operator ^ and the other the operator $.

$

Matches the end of the text. If the multiline flag is set to true, it also applies immediately before a line break character. For example, /r$/ does not match r in "run", but finds a match in "run".

^

Corresponds to the beginning of the text. If the multiline flag is set to true, it also applies immediately after a line break character. For example, /^A/ does not match 'A' in "One Target", but matches 'A' in "Target Found".

Browser other questions tagged

You are not signed in. Login or sign up in order to post.