Hi again, dearest devs on earth. 🌎 🌍 🌏
I am back in business, bringing the last part of our Regex series.
Thanks a lot for been following and interacting with the article so far. :) It is really a great pleasure having you all here. 🙇♂️
If you are puzzled, please check out the parts 1/3 and 2/3 so this last one may make more sense. (or not 🤷♂️)
I am going to cover few more topics and after that I am sure you are good to go and apply your knowledge by yourself. At least it has been my aim since the beginning. 🎯
Take you mug filled with coffee and let's cut to the chase. ☕
Lookahead (Positive and Negative)
The name kind of describe what it does. Now, we only need to know how to "write" it and where to use it. Don't panic! I am here.
-
Positive Lookahead
(?= )
👍
The positive lookahead
operator returns an array if the pattern was found or null
instead.
Just to be more concise, when using along with the .match()
method, the result will be either [ '', index: 0, input: '<the pattern here>', groups: undefined ]
or null
.
When working with lookaheads
I particularly prefer using .test()
than match()
because, in the end, we are expecting an answer either "yes" or "not". (true
or false
)
I know, more gibberish so let's use an example here.
Imagine you have built a login form in your website and you want all the passwords to fulfill a given criteria before accept storing them. Let's say, it must:
- have a minimum of 10 characters,
- have up to 15 characters, (🙏 always use more if possible 💡)
- should include one or more numbers on it.
Of course we could do that validation using plain JavaScript but, trust me, it would be as painful as stubbing your little toe on a corner. 😹 💦
This is why using lookahead
comes to our rescue.
// Not good at all tbh
let goodPassword = "neverput1234"
Our lookahead
Regex:
let ourRegex = /(?=\w{10,15})(?=\D*\d)/
Express explanation: ⏩
-
(?=\w{10,15})
: it will search for alphanumeric characters in a range between 10 and 15. -
(?=\D*\d)
: it will search for zero or more non-numeric characters (\D*
) followed by a number (/d
).
In order to return a pattern of characters, it must fulfill both requirements above. Think it as the &&
(and) logical operator.
Boilerplate same from previous parts:
let hasPattern = ourRegex.test(goodPassword);
let patternMatched = goodPassword.match(ourRegex);
console.group('The Result of our comparison');
console.log('Has Pattern?:', hasPattern);
console.log('The Pattern: ', patternMatched);
console.groupEnd();
Should log on console:
The Result of our comparison
Has Pattern?: true
The Pattern: [ '', index: 12, input: 'neverput1234', groups: undefined ]
-
Negative Lookahead
(?! )
👎
I am sure you already figured out how it works. It is like making the same question but in "negative" way. (⚠️ lack of grammatical jargon detected! 😬)
We have this sample string:
let status = 'people happy people happy people happy';
Your question would be like:
" - Do we have at least one person not happy there?"
💡 I didn't write unhappy
because it would be any thing other than happy
, for instance, bored
. 😅
let ourRegex = /people(?!\shappy)/;
let hasPattern = ourRegex.test(status);
let patternMatched = status.match(ourRegex);
console.group('The Result of our comparison');
console.log('Has Pattern?:', hasPattern);
console.log('The Pattern: ', patternMatched);
console.groupEnd();
The Regex's answer (🤖) would be: "- There is no people other than happy there. (false
)"
The Result of our comparison
Has Pattern?: false
The Pattern: null
I hope you have got the point. It is a little tricky indeed. 🧠 💥
Capturing Groups ()
We can also use parenthesis to capture patterns found in a given group, for example:
- In a mixed grouping of chars:
let alleatorySentence = 'Publishment is not a punishment.';
let ourRegex = /P(ublis|unis)hment/gi;
let hasPattern = ourRegex.test(alleatorySentence);
let patternMatched = alleatorySentence.match(ourRegex);
Brings us the following:
The Result of our comparison
Has Pattern?: true
The Pattern: [ 'Publishment', 'punishment' ]
Reusing patterns:
let isnow = 'Snow Snow Snow';
let ourRegex = /((\w+)\s)/g;
In the console:
(Remember to use the provided console.log() boilerplate above)
The Result of our comparison
Has Pattern?: true
The Pattern: [ 'Snow ', 'Snow ' ]
☝️ The last Snow
in the original string is not followed by a empty space \s
so it was not included in the results.
Search and Replace
This is very interesting. Everybody knows what the replace()
method does ...
let activity = "I like sleeping a lot"
let beHealthy = activity.replace(/sleeping/, "surfing and coding")
The beHealthy
variable now holds the I like surfing and coding a lot
value. 🥰
But how about switching places?
let poorPhrase = 'I and you went to a bootcamp last year.';
let switchRegex = /(\w+)\s(\w+)\s(\w+)/
let slightlyBetter = poorPhrase.replace(switchRegex, '$3 $2 $1')
What have just happened?
In short, our regex have matched those values inside of the parenthesis:
-
I
as$1
, -
and
as$2
, -
you
as$3
.
And in that sentence $3 $2 $1
we have switched their places in the string. Cool, isn't it? 😝
🤫 Just pretend you didn't see the lowercase you
in the beginning of the phrase. 🤫
And that is it, guys. We have reached the end of the regex series.
I don't remember anything else to add here. Maybe the trim()
method but to be honest, it doesn't need any deep explanation.
I would like to thank you all for sticking with me until here and I hope I can bring you more interesting stuff very soon.
Take care everybody and Toodle Pip! 🖖
Top comments (0)