Use look-arounds:
(?<=p_auth=).*?(?=&)
See regex demo
The look-behind (?<=p_auth=)
and the look-ahead (?=&)
do not consume characters as they are zero-width assertions. They just check for the substring presence either before or after a certain subpattern.
A couple more words about (?<=p_auth=)
. It is a positive look-behind. Positive because it require a pattern inside it to appear on the left, before the "main" subpattern. If the look-behind subpattern is found, the result is just "true" and the regex goes on checking the rest of subpatterns. If not, the match is failed, the engine goes on looking for another match at the next index.
Here is some description from regular-expressions.info:
It [the look-behind] tells the regex engine to temporarily step backwards in the string, to check if the text inside the lookbehind can be matched there. (?<!a)b
matches a "b"
that is not preceded by an "a"
, using negative lookbehind. It doesn't match cab, but matches the b
(and only the b
) in bed
or debt
. (?<=a)b
(positive lookbehind) matches the b
(and only the b
) in cab, but does not match bed
or debt
.
In most cases, you do not really need look-arounds. In this case, you could just use a
p_auth(.*?)&
And get the first capturing group value.
The .*?
pattern will look for any number of characters other than a newline, but as few as possible that are required to find a match. It is called lazy dot matching, because the ?
symbol makes the *
quantifier stop before the first symbol that is matched by the subsequent subpattern in the regular expression.
The .*&
would match all the substring until the last &
because *
quantifier is greedy - it will consume as many characters it can match as possible.
See more at Repetition with Star and Plus regular-expressions.info page.