Reputation: 16506
I have a string of text that will look like
· 7:30pm · a/a · ★★ · fri sold out · Multi-day event ·
or
· 7:30pm · a/a · ★★ · sold out · Multi-day event ·
I want to capture sold out
if that text exists or fri sold out
if that text exists.
My attempted regex is /^.*\s(\w*\ssold out|sold out).*$/
but that is only capturing sold out
.
How do I capture either string of text?
Edit: I will not always have the ·
anchors on either side. I also want to be able to grab the same info from, i.e.:
10pm · 21+ · ★ · late show - sold out ·
Upvotes: 2
Views: 1622
Reputation: 6511
You're almost there. The problem with your pattern is the first .*
By default, the regex engine is greedy, .*
consumes as much as it can, and it has precedence over the rest of the pattern (it's on the left). To change this behaviour, you can use a lazy quantifier. Adding the extra "?" in .*?
makes it repeat as few as possible.
/^.*?\s(\w*\ssold out|sold out).*$/
Now that we made clear what was wrong, let's see a few more things. I think \w*
should require at least 1 char, so we can change the quantifier and use \w+
. Also, we can make it shorter using a non-capturing group to make the \w*\s
optional, thus shortening the pattern:
/^.*?\s((?:\w+\s)?sold out).*$/
And if you don't actually need to match the whole line, you can use:
/\s((?:\w+\s)?sold out)/
Upvotes: 2
Reputation: 1074276
You can capture an optional \w+
in front of sold out
(fortunately, have that nice solid sold out
to work with):
var rex = /((?:[\w]+ )?sold out)/;
var match = str.match(rex);
var text = match && match[1];
Live Example:
test("· 7:30pm · a/a · ★★ · fri sold out · Multi-day event ·");
test("· 7:30pm · a/a · ★★ · sold out · Multi-day event ·");
test("10pm · 21+ · ★ · late show - sold out ·");
function test(str) {
var rex = /((?:[\w]+ )?sold out)/;
var match = str.match(rex);
var text = match && match[1];
snippet.log("'" + str + "' =>");
snippet.log("'" + text + "'");
}
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Here's an explanation of that regex, but basically the outer (...)
is a capture group, then (?:[\w]+ )?
says "optionally match one or more word characters followed by a space" (the ?
after the non-capturing group (?:...)
is what makes it optional), and of course sold out
is our anchoring text.
Upvotes: 4
Reputation: 67968
★+\s*\·\s*([^·]+)(?=·)
You can use this and grab the group
.See demo.
https://regex101.com/r/cJ6zQ3/1
var re = /★+\s*\·\s*([^·]+)(?=·)/g;
var str = ' · 7:30pm · a/a · ★★ · fri sold out · Multi-day event ·\n\nor\n\n · 7:30pm · a/a · ★★ · sold out · Multi-day event ·';
var m;
while ((m = re.exec(str)) !== null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}
Upvotes: 1