多个正则表达式模式需要start ^和end $

If given [name=anystring] or #anystring where anystring is a string which has already had any whitespace removed, I wish to return anystring.

Before attempting both, I successfully performed them individually.

$pattern = "/^#(.+)$/";
preg_match($pattern, '#anystring', $matches);
preg_match($pattern, '[name=anystring]', $matches);

$pattern = "/^\\[name=(.+)\\]$/";
preg_match($pattern, '#anystring', $matches);
preg_match($pattern, '[name=anystring]', $matches);

And then I tried to combine them.

# with start ^ and end $ on both
$pattern = "/^#(.+)$|^\\[name=(.+)\\]$/";
preg_match($pattern, '#anystring', $matches);
preg_match($pattern, '[name=anystring]', $matches);

# without start ^ and end $ on both
$pattern = "/^#(.+)|\\[name=(.+)\\]$/";
preg_match($pattern, '#anystring', $matches);
preg_match($pattern, '[name=anystring]', $matches);

While I "kind of" get what I am looking for, the second pattern [name=(.+)] returns an array with three elements.

Should I have and end $ after the first pattern and a start ^ before the second pattern? Can this result in the second pattern returning an array with three elements?

EDIT. Show how one version displays more array elements

<?php

$pattern = "/^(?:#(.+)|\\[name=(.+)\\])$/s";
preg_match($pattern, '#anystring', $matches);
print_r($matches);
preg_match($pattern, '[name=anystring]', $matches);
print_r($matches);

(
    [0] =&gt; #anystring
    [1] =&gt; anystring
)
Array
(
    [0] =&gt; [name=anystring]
    [1] =&gt; 
    [2] =&gt; anystring
)

You are looking for a branch reset group where numbering of capturing groups begins from the last ID before the group:

^(?|#(.+)|\[name=(.+)])$
  ^^

See the regex demo

enter image description here

Details

  • ^ - start of string
  • (?| - start of the branch reset group
    • #(.+) - a # and then Group 1 capturin 1+ chars, as many as possible
    • | - or
    • \[name= - a [name= substring
    • (.+) - Group 1 (again) matching 1+ chars other than line break chars, as many as possible
    • ] - a ]
  • ) - end of the branch reset group
  • $- end of string.

You can combine 2 regexes using a non capturing group:

(?:pattern1|pattern2)

I wrote this regex which will capture on both strings:

(?:\[\w+=(?<bracketword>\w+)\]|\#(?<word>\w+))

Your match will either have array key bracketword, or word. Check it out on the regex101 link below.

https://regex101.com/r/AmgHTS/1/

You can also use start and end string ^ and $ if you like. In my edited regex, my test string is two lines (one for each string), so i had to use the multi line flag too.

https://regex101.com/r/AmgHTS/2/

To capture only anything with both use Lookbehind like this :

(?<=#|name=)([^\[#\]]+)

https://regex101.com/r/AmgHTS/4/

for more check :

https://regex101.com/r/AmgHTS/5