It would really help you out if you write things out with /x which ignores whitespace. Using it allows you to document your regex which helps find inefficiencies in it and also ways to improve it. Here's what you have (I've not escaped the actual spaces you encoded, but it should give you an idea of how much easier it is to read).
( # EITHER
(?:\w+ )? # [uncaptured word characters] OR NOTHING
| # OR
( # EITHER
(?:(j|J)e ) # [uncaptured J or j]e
| # OR
(tu ) # tu
| # OR
(il ) # il
)? # OR NOTHING
)
(?:ne )? # PLUS MAYBE [uncaptured ne]
(?: # EITHER [uncaptured]
veu(x|t)\b # veux/veut AND word boundary
| # OR
voul(ais|ait)\b # voulais/voulait AND word boundary
| # OR
voudr(ais|ait)\b# voulais/voulait AND word boundary
| # OR
voul(ez) # voul AND ez
)
-? # AND MAYBE -
(?:vous)? # AND MAYBE [uncaptured vous]
(?: pas)? # AND MAYBE [uncaptured pas]
qu(e |') # AND que or qu'
It becomes obvious where to add fenceop's suggestion of (?: \w+\b)* in here (I'd also add on an extra ?
otherwise if you have two que/qu' it will gobble up all but the last one), but first some things you can improve on:
In the first group, notice that both of the initial two options include a group which is followed by ?
(exactly 0 or 1 times). This means it can also match nothing at all. You can just put the ?
at the end of the entire first capture group. Also, you have a space after each element in the nested options (for pronouns). You can just put this after all of them. Likewise, no need for parentheses. For for single letter options, character classes are much more readable and common, so you can change (j|J)
to [Jj]
. So ((?:\w+ )?|((?:(j|J)e )|(tu )|(il ))?)
can be trimmed down to (\w+|([Jj]e|tu|il) )?
. But since \w is just a default collect if not the ones you've specified, you can drop it even further to a single set of options rather than needing to nest it. But then again, since \w+ would match the others, you can just have \w+. I don't think that's what you want, though.
In the the group with the verb conjugation, again, character classes are nice and the (ez) does nothing but add a capture group. Presuming you actually meant to include the word boundary after all of them, you can just use that after the options group. So (?:veu(x|t)\b|voul(ais|ait)\b|voudr(ais|ait)|voul(ez))
can be trimmed down to (veu[xt]|voulai[st]|voudrai[st]|voulez)\b
.
Also, some other improvements: using \w+
to try to match a sequence of letters will fail if there's any punctuation which I believe in French is quite rather common. You may wish to specify your own character as [A-Za-z,.:;'‘’“”«»()-]
(adding in accented variants needed for French, hyphen must go at the very end or very beginning), or just use \D
which is a non-white space character. For what you're doing, there's probably no harm in using \D
in place of \w
.
With the number of non-capturing groups you have, you might want to instead use named capture groups and just ignore all other results, but that's me personally. Given my suggestions you will get using /x (again, spaces not fully escaped), I'd recommend something closer to this (using named captures pre, neg1, verb, pron, neg2, and extra — extra will contain the text you have in bold):
(?<pre> # EITHER
[Jj]e # Je OR je
| # OR
tu # tu
| # OR
il # il
)? # OR NOTHING
\d+ # AND AT LEAST ONE spacing character
(?<neg1>ne\s+)? # PLUS MAYBE ne AND AT LEAST ONE spacing character
(?<verb> # EITHER
veu[xt] # veux/veut
| # OR
voulai[st] # voulais/voulait
| # OR
voudrai[st] # voulais/voulait
| # OR
voulez # voulez
)
(?<pron>-vous)? # AND MAYBE -vous
(?<neg2>\spas)? # AND MAYBE (spacing character AND pas)
(?<extra>:\s\S+)*?# AND AS MANY SEQUENCES OF (spacing character AND AT LEAST ONE non-spacing) AS NECESSARY
qu(e |') # AND que or qu'
Or reduced down (without named captures:)
([Jj]e|tu|il)?\d+(ne\s+)?(veu[xt]|voulai[st]|voudrai[st]|voulez)(-vous)?(\dpas)?(\s\S+)*?qu(e |')
Also, a French questions I don't know the answer to. Does pas require ne? If so, and you wish to exclude ungrammatical phrases, you will need to set up a rather large alternate pattern.