Home > front end >  Regex in javascript using RegExp contructor for the strings that ends with some string X and contain
Regex in javascript using RegExp contructor for the strings that ends with some string X and contain

Time:08-14

I got RE of strings that starts with some string X and contains some string Y which was

const startsWith = 't'
const contains = 'te'
const re = new RegExp(`(?=.*${contains})^${startsWith}`)
re.test('teacher') // Result = true

But when I try to change it to ends with X and contains Y like

const endsWith = 'e'
const contains = 'te'
const re = new RegExp(`(?=.*${contains})${endsWith}\$`)
re.test('ate') // Result = false

I did not get the desired result

I need a regex which would give true when word like 'ate' contains 'te' and also ends with 'e', also gives true when word like 'steve' contains 'te' and ends with 'e'. Currently my endsWith regex giving false on both.

CodePudding user response:

The "endsWith" part is always at the end of the string.

The generated regex looks like this (?=.*te)e$ and when the lookahead succeeds asserting (non consuming) te, the position is still at the start of the string.

The next part of the pattern tries to match e at the end of the string, but the position did not move yet and it did not match at before it to get to the e at the end.

You might write the pattern using .* in between to get to the end of the string, and add an anchor ^ before the lookahead to perform the assertion only once.

Note that you can escape the \$ but you don't have to.

const endsWith = 'e'
const contains = 'te'
const re = new RegExp(`^(?=.*${contains}).*${endsWith}$`)
console.log(re.test('ate'))

CodePudding user response:

1st let's understand why the 1st one is working and why the 2nd one is not working.

Example First:

const startsWith = 't'
const contains = 'te'
const re = new RegExp(`(?=.*${contains})^${startsWith}`)
re.test('teacher') // Result = true

Debug:

(?=.*te)^t

Explain:

Here (?=.*te) is "Positive lookahead", which means regex will start matching this and then will look ahead for the next conditions/rules.

(
    ?=              Matches a group after the main expression (^t) without including it in the result.
    .               DOT, Matches any character except linebreaks
    *               Matches 0 or more of the preceding token
    t               Check for character 't'
    e               Check for character 'e'
)
^                   Matches the beginning of the string. This matches a position, not a character.
t                   Check for character 't'

Human Explain:

Find every string which contains 'te' and ready to look after next rule which is find string which starts with 't'

Hence:

teacher             //true, because it has 'te' and starts with 't'
thirdteacher        //true, because it has 'te' and starts with 't'
twoteacher          //true, because it has 'te' and starts with 't'
myteacher           //false, because it has 'te' but does not start with 't'

Example Second:

const endsWith = 'e'
const contains = 'te'
const re = new RegExp(`(?=.*${contains})${endsWith}\$`)
re.test('ate') // Result = false

Debug:

(?=.*te)e$

Explain:

Here (?=.*te) is "Positive lookahead", which means regex will start matching things after the main expression.

(
    ?=              Matches a group after the main expression (e$) without including it in the result.
    .               DOT, Matches any character except linebreaks
    *               Matches 0 or more of the preceding token
    t               Check for character 't'
    e               Check for character 'e'
)
e                   Check for character 'e'
$                   Matches the end of the string. This matches a position, not a character.

Human Explain:

Find every string which contains 'te' but as the main expression first find a string which ends as the last character 'e'. it's end man! whoa!! yeah!! end .. end.. nothing after to match... it's ending.

  • Since... "Positive lookahead" failed here due to the main expression ends the search here using '$'

Hence "Positive lookahead" can not proceed for "lookahead"

Hence:

regex will find ... nothing, no match Ssshhhh... silence

So what is the solution?

You have 2 options either use @The fourth bird solution which is '(?=.*te).*e$' in debug mode.

Here '.' is the main expression and gives "Positive lookahead" a chance to move and find strings and matches after ..

(
    ?=              Matches a group after the main expression (e$) without including it in the result.
    .               DOT, Matches any character except linebreaks
    *               Matches 0 or more of the preceding token
    t               Check for character 't'
    e               Check for character 'e'
)
.                   DOT, Matches any character except linebreaks
*                   Matches 0 or more of the preceding token
e                   Check for character 'e'
$                   Matches the end of the string. This matches a position, not a character.

Human Explain:

Hey! regex please bring me a string which contains 'te' and ends with 'e'

Execution Pipeline for 'soulmate':

(?=.*te)            -- did you found 'te' yes 'solema*te*'
.*                  -- main expression is find everything, did you found, yes 'soulmate'
e$                  -- last expression is 'ends with e', did you find, yes 'soulmat*e*'

Master, here is the result - 'soulmate'

// false          tomato page
// false          yellow-teeth
// true           teeth-color-is-white
// true           ate
// false          future terminator
// false          AI is awful and should never be replaced with the human race.
// true           AI is good for telephones but awful for the human race
// true           I am running late
// true           e-gate
// true           soulmate
// false          time
// false          race
// false          ate-milan-cafes
// true           tell me the truth if mighty god is everywhere

Another option is using the native Javascript function. startsWith, includes and endsWith.

Example:

<script>
    var first = "teacher";
    var startwith = first.startsWith("t");
    var contains = first.includes("te");
    alert((contains && startwith)); // true
    var second = "ate";
    var contains = first.includes("te");
    var endwith = second.endsWith("e");
    alert((contains && endwith)); // true
</script>

-- Thank you

  • Related