Regex curly braces and quotes get inner text - php

In the following string {lang('stmt')} I want to get just the stmt where it may also be as follows {lang("stmt")}.
I'm bad with regex, I've tried {lang(.*?)} which gives me ('stmt').

You might match {lang(" or {lang(' and capture the ' or " using a capturing group. This group can by used with a backreference to match the same character.
Use \K to forget what was previously matched.
Then match 0+ characters non greedy .*? and use a positive lookahead using the backreference \1 to assert what follows is ')} or ")}
\{lang\((['"])\K.*?(?=\1\)})
Regex demo

Match either ' or " with a character set, then lazy-repeat any character until the first capture group can be matched again:
lang\((['"])(.*?)\1
https://regex101.com/r/MBKhX3/1
In PHP code:
$str = "{lang('stmt')}";
preg_match('/lang\(([\'"])(.*?)\1/', $str, $matches);
print(json_encode($matches));
Result:
["lang('stmt'","'","stmt"]
(the string you want will be in the second capture group)

Try this one too.
lang\([('")][a-z]*['")]\)

Keep ( and ) outside the (.*) to get value without ( and )
regex:
{lang\('|"['|"]\)}
php: '/{lang\([\'|"](.*?)[\'|"]\)}/'

Related

How to capture all phrases which doesn't have a pattern in the middle of theirself?

I want to capture all strings that doesn't have the pattern _ a[a-z]* _ in the specified position in the example below:
<?php
$myStrings = array(
"123-456",
"123-7-456",
"123-Apple-456",
"123-0-456",
"123-Alphabet-456"
);
foreach($myStrings as $myStr){
echo var_dump(
preg_match("/123-(?!a[a-z]*)-456/i", $myStr)
);
}
?>
You can check the following solution at this Regex101 share link.
^(123-(?:(?![aA][a-zA-Z]*).*)-456)|(123-456)$
It uses regex non-capturing group (?:) and regex negative lookahead (?!) to find all inner sections that do not start with 'a' (or 'A') and any letters after that. Also, the case with no inner section (123-456) is added (with the | sign) as a 2nd alternative for a wrong pattern.
A lookahead is a zero-length assertion. The middle part also needs to be consumed to meet 456. For consuming use e.g. \w+- for one or more word characters and hyphen inside an optional group that starts with your lookahead condition. See this regex101 demo (i flag for caseless matching).
Further for searching an array preg_grep can be used (see php demo at tio.run).
preg_grep('~^123-(?:(?!a[a-z]*-)\w+-)?456$~i', $myStrings);
There is also an invert option: PREG_GREP_INVERT. If you don't need to check for start and end a more simple pattern like -a[a-z]*- without lookahead could be used (another php demo).
Match the pattern and invert the result:
!preg_match('/a[a-z]*/i', $yourStr);
Don't try to do everything with a regex when programming languages exist to do the job.
You are not getting a match because in the pattern 123-(?!a[a-z]*)-456 the lookahead assertion (?!a[a-z]*) is always true because after matching the first - it has to directly match another hyphen like the pattern actually 123--456
If you move the last hyphen inside the lookahead like 123-(?!a[a-z]*-)456 you only get 1 match for 123-456 because you are actually not matching the middle part of the string.
Another option with php can be to consume the part that you don't want, and then use SKIP FAIL
^123-(?:a[a-z]*-(*SKIP)(*F)|\w+-)?456$
Explanation
^ Start of string
123- Match literally
(?: Non capture group for the alternation
a[a-z]*-(*SKIP)(*F) Match a, then optional chars a-z, then match - and skip the match
| Or
\w+- Match 1+ word chars followed by -
)? Close the non capture group and make it optional to also match when there is no middle part
456 Match literally
$ End of string
Regex demo
Example
$myStrings = array(
"123-456",
"123-7-456",
"123-Apple-456",
"123-0-456",
"123-Alphabet-456",
"123-b-456"
);
foreach($myStrings as $myStr) {
if (preg_match("/^123-(?:a[a-z]*-(*SKIP)(*F)|\w+-)?456$/i", $myStr, $match)) {
echo "Match for $match[0]" . PHP_EOL;
} else {
echo "No match for $myStr" . PHP_EOL;
}
}
Output
Match for 123-456
Match for 123-7-456
No match for 123-Apple-456
Match for 123-0-456
No match for 123-Alphabet-456
Match for 123-b-456

Regex matching {{> (lookup. 'superman')}}

I need regex that will do result in following
Given this notation:
{{> (lookup. 'needle')}}
Tt returns result :
["needle"]
I tried with this one, but it matches everything {{>\(.(.+?)}}
You might use make use of a capturing group and instead of a non greedy quantifier .+? make use of a negated character class
{{>\h*\([^(']+'([^')]+)'\)}}
{{> Match {{>
\h* Match 0+ horizontal whitespace chars (or \h+ for 1 or more)
\([^(']+ Match ( and then 1+ times any char except ( or '
'( Match ' and start capture group 1
[^')]+ Match 1+ times any char except ' or )
)' Close group 1 and match '
\)}} Match )}}
Regex demo
In the replacement use
["$1"]
Output
["needle"]
Edit
If the lookup part should be static, you could update the pattern to:
{{>\h*\(lookup[^']+'([^')]+)'\)}}
Regex demo
If the notation is going to be exactly the same as written, {{> \(lookup\s*\. '(.*?)'\)}} should solve your problem. It looks for literal versions of all your characters, and then uses a capture group to collect only the text between ' marks. (Note that this regex needs to be changed if the capture text includes ' marks.)
Edit: regex now matches any number of spaces between lookup and .
Try it here!

How to find and replace single quote in some string?

Because assert — Checks if assertion is FALSE in php after 7.2 version changed need using string as the assertion is DEPRECATED as of PHP 7.2.
And I want use replace in path php storm function with regex, changing all point where is it was, how it's look this is regular expression ?
example pioints:
assert('is_array($config)');
assert('is_string($location)');
assert('is_string($entityId)');
I just found and replace first quote, just like this
.*?(\bassert\('\b)[^$]* replace to assert(. But how it be with last quote I don't know.
result must be
assert(is_array($config));
assert(is_string($location));
assert(is_string($entityId));
with first single quote I found solution, need find solution to last single quote
Any ides ?
One option to match a single quote only could be to make use of \G to assert the position at the end of the previous match. Make use of \K to forget what was currently matched and then match the single quote.
In the replacement use an empty string.
(?:^.*?\bassert\(|\G(?!^))[^']*\K'(?=.*\);)
About the pattern
(?: Non capturing group
^.*?\bassert\( Match from the start of the string in a non greedy way until you encounter assert(
| Or
\G(?!^) Assert position at the previous match, not at the start
) Close non capturing group
[^']*\K' Match 0+ times not ', forget what was matched and match '
(?=.*\);) Assert what is on the right is a closing parenthesis and ;
Regex demo
Another way could be to use 3 capturing groups, match the ' that you want to remove and use the groups in the replacement:
^(.*?\bassert\()'([^']+)'(.*)$
Regex demo
We would better off starting with an expression with more boundaries, such as:
.*?(\bassert\b)\s*\(('|")\s*([^'"]*?)\s*('|")\s*\)\s*;
Test
$re = '/.*?(\bassert\b)\s*\((\'|")\s*([^\'"]*?)\s*(\'|")\s*\)\s*;/s';
$str = 'assert (" is_string($entityId)") ;';
$subst = '$1($3);';
echo preg_replace($re, $subst, $str);
The expression is explained on the top right panel of this demo, if you wish to explore further or modify it, and in this link, you can watch how it would match against some sample inputs step by step, if you like.

Get only alphanumeric part of regex string

Let's say I can have strings like these:
^(www.|)mysite1.com$
^(.*)mysite2.com(.*)$
^(www\.|)mysite3\.com$
How do I get only the mysite1, mysite2 or mysite3 part of such strings. I tried set the non-alphanumeric parts to empty string using:
preg_replace("/[^A-Za-z0-9]/", '', $mystring);
But that returns me
mysite1com
mysite2com
mysite3com
Thanks in advance.
What you might do is use preg_match instead of preg_replace and use for example this regex:
\^\([^)]+\)\K[A-Za-z0-9]+
That would match
\^ # Match ^
\( # Match (
[^)]+ # Match not ) one or more times
\) # Match )
\K # Reset the starting point of the reported match
[A-Za-z0-9]+ # Match one or more upper/lowercase character or digit
For example:
preg_match("/\^\([^)]+\)\K[A-Za-z0-9]+/", "^(www.|)mysite1.com$", $matches);
echo $matches[0];
Demo
With preg_replace an approach could be to use 3 capturing groups where the value you want to keep is in the second group.
In the replacement, you would use $2:
(\^\([^)]+\))([A-Za-z0-9]+)(.*)
preg_replace("/(\^\([^)]+\))([A-Za-z0-9]+)(.*)/", '$2', $mystring);
Demo

PHP regular expression start and end with given strings

I have a string like this
05/15/2015 09:19 PM pt_Product2017.9.abc.swl.px64_kor_7700 I need to select the pt_Product2017.9.abc.swl.px64_kor from that. (start with pt_ and end with _kor)
$str = "05/15/2015 09:19 PM pt_Product2017.9.abc.swl.px64_kor_7700";
preg_match('/^pt_*_kor$/',$str, $matches);
But it doesn't work.
You need to remove the anchors, adda \b at the beginning to match pt_ preceded with a non-word character, and use a \S with * (\S shorthand character class that matches any character but whitespace):
preg_match('/\bpt_\S*_kor/',$str, $matches);
See regex demo
In your regex,^ and $ force the regex engine to search for the ptat the beginning and _kor at the end of the string, and _* matches 0 or more underscores. Note that regex patterns are not the same as wildcards.
In case there can be whitespace between pt_ and _kor, use .*:
preg_match('/\bpt_.*_kor/',$str, $matches);
I should also mention greediness: if you have pt_something_kor_more_kor, the .*/\S* will match the whole string, but .*?/\S*? will match just pt_something_kor. Please adjust according to your requirements.
^ and $ are the start and end of the complete string, not only the matched one. So use simply (pt_.+_kor) to match everything between pt_ and _kor: preg_match('/(pt_+_kor)/',$str, $matches);
Here's a demo: https://regex101.com/r/qL4fW9/1
The ^ and $ that you have used in the regular expression means that the string should start with pt AND end with kor. But it's neither starting as such, nor ending with kor (in fact, ending with kor_7700).
Try removing the ^ and $, and you'll get the match:
preg_match('/pt_.*_kor/',$str, $matches);

Categories