I want to select all text before and after a specific substring, I used the following expression to do that, but it not selecting all the needed text:
/^(?:(?!\<\?php echo[\s?](.*?)\;[\s?]\?\>).)*/
for example:
$re = '/^(?:(?!\<\?php echo[\s?](.*?)\;[\s?]\?\>).)*/';
$str = 'customFields[<?php echo $field["id"]; ?>][type]';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
it will select only this part customFields[, while the expected result should be customFields[ and ][type]
check this link for debugging
The pattern ^(?:(?!\<\?php echo[\s?](.*?)\;[\s?]\?\>).)* uses a tempered greedy token which matches any character except a newline from the start of the string ^ that fulfills the assertion of the negative lookahead.
That will only match customFields[
For your example data you could make use of a tempered greedy token regex demo, but instead you could also just make use of a negated character class and SKIP FAIL:
^[^[]+\[|<\?php echo\s(.*?)\;\s\?\>(*SKIP)(*FAIL)|\]\[[^]]*\]
Regex demo | Php demo
For example
$re = '/^[^[]+\[|<\?php echo\s(.*?)\;\s\?\>(*SKIP)(*FAIL)|\]\[[^]]*\]/';
$str = 'customFields[<?php echo $field["id"]; ?>][type]';
preg_match_all($re, $str, $matches, PREG_SET_ORDER);
print_r($matches);
Result
Array
(
[0] => Array
(
[0] => customFields[
)
[1] => Array
(
[0] => ][type]
)
)
To get a more exact match you might also use capturing groups:
^((?:(?!<\?php echo[\s?](?:.*?)\;\s\?>).)*)<\?php echo\s(?:.*?)\;[\s?]\?>(.*)$
regex demo | Php demo
What about using positive lookarounds:
(.*)(?=\<\?php echo)|(?<=\?\>)(.*)
Demo
Related
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] => #anystring
[1] => anystring
)
Array
(
[0] => [name=anystring]
[1] =>
[2] => 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
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
My try:
$a = preg_split("/[0-9](\-)[0-9]/", $d);
print_r($a);
If $d=sometext9-9sometext, I want to be able to get from print_r($a);
Array
(
[0] => sometext9
[1] => -
[2] => 9sometext
)
What am I missing?
You may use
$re = "/(?<=[0-9])(-)(?=[0-9])/";
$str = "sometext9-9sometext";
$a = preg_split($re, $str, $matches, PREG_SPLIT_DELIM_CAPTURE);
print_r($a);
See IDEONE demo. Since the - is in Group 1 (enclosed with (...)) and we use PREG_SPLIT_DELIM_CAPTURE flag, the hyphen is returned as part of the resulting array.
PREG_SPLIT_DELIM_CAPTURE
If this flag is set, parenthesized expression in the delimiter pattern will be captured and returned as well.
The lookarounds (?<=[0-9]) and (?=[0-9]) check for but do not consume the digits on both ends thus they are kept in the elements adjoining to -. See more on that behavior at Lookarounds Stand their Ground.
I'm using this pattern to check if certain words exists in a string:
/\b(apple|ball|cat)\b/i
It works on this string cat ball apple
but not on no spaces catball smallapple
How can the pattern be modified so that the words match even if they are combined with other words and even if there are no spaces?
Remove \b from the regex. \b will match a word boundary, and you want to match the string that is not a complete word.
You can also remove the capturing group (denoted by ()) as it is not required any longer.
Use
/apple|ball|cat/i
Regex Demo
An IDEONE PHP demo:
$re = "/apple|ball|cat/i";
$str = "no spaces catball smallapple";
preg_match_all($re, $str, $matches);
print_r($matches[0]);
Results:
[0] => cat
[1] => ball
[2] => apple
I need a regex that can actually get any number that is inserted after "ab" and "cr". For example, I have a string like this:
rw200-208-ab66
fg200-cr30-201
I need to print ab66 and cr30.
I have tried using strpos:
if (strpos($part,'ab') !== false) {
$a = explode("ab", $part);
echo 'ab'.$a[1];
}
That does not work for the second item.
You could use \K to discard the previously matched chars from printing at the final. The below regex would give you the number which exists next to ab
or cr.
(?:ab|cr)\K\d+
To get the number with alphabets also, use
preg_match_all('~(?:ab|cr)\d+~', $str, $match);
Use this regex:
(?>ab|cr)\d+
See IDEONE demo:
$re = "#(?>ab|cr)\d+#";
$str = "rw200-208-ab66\nfg200-cr30-201";
preg_match_all($re, $str, $matches);
print_r($matches[0]);
Output:
Array
(
[0] => ab66
[1] => cr30
)
In PHP I have a string that can contain any quantity of customer placeholders. In this case I am using '[%' & '%]' as the custom placeholders for each iteration.
If my string is equal to:
"test [%variable1%] test test [%variable2%]"
How do I extract the 'variables' so I will have something like this:
array(
[0] => variable1,
[1] => variable2
);
At the moment I have: \b[\[%][a-z.*][\]%]\b but I know this is incorrect.
Use preg_match_all function to do a global match.
$re = "~(?<=\[%).*?(?=%])~m";
$str = "test [%variable1%] test test [%variable2%]";
preg_match_all($re, $str, $matches);
print_r($matches[0]);
(?<=\[%) positive lookbehind which asserts that the match must be preceeded by [% symbols. (?=%]) asserts that the match must be followed by %] symbols. .*? will do a non-greedy match of any character zero or more times.
Output:
Array
(
[0] => variable1
[1] => variable2
)
DEMO
$re = "/\\[%(.*?)%\\]/";
$str = "test [%variable1%] test test [%variable2%]";
preg_match_all($re, $str, $matches);
Regex used:
/\[%(.*?)%\]/g