preg match between two strings - php

I need help with this preg match. I tried this from other post but did not get the result. So finally posting it.
I am trying to extract z,a,b from first and a from second example.
1) Write a function operations with parameter z,a,b and returns b.
2) write a function factorial with parameter a.
This is what I tried so far:
preg_match_all('/\parameter(.*?)\and?/', $question, $match);
$questionVars = $match[1];
print $questionVars;
Thank you so much!

Your solution can be different depending on actual requirements.
If you need a string after parameter as a whole word that can consist of word and comma chars you may use
preg_match('~\bparameter\s+\K\w+(?:\s*,\s*\w+)*~', $s, $m)
See the regex demo. The \bparameter\s+ matches a word boundary, parameter and 1+ whitespace chars, and all this text is omitted with the help of \K, the match reset operator. \w+(?:\s*,\s*\w+)* matches and returns the 1+ word chars followed with 0+ repetitions of a comma enclosed with optional whitespace chars and again 1+ word chars.
If you plan to get those comma-separated chunks separately, use
preg_match_all('~(?:\G(?!^)\s*,\s*|\bparameter\s+)\K\w+~', $s, $m)
See another regex demo. Here, (?:\G(?!^),\s*|\bparameter\s+) will either match the whole word parameter with 1+ whitespace after (\bparameter\s+, as in the previous solution) or the end of the previous successful match with , enclosed with optional whitespace chars (\G(?!^)\s*,\s*). The \K will omit the text matched so far and \w+ will grab the value. You may replace with [^,]* to grab 0+ chars other than a comma.

Related

Why regex with lookaheads doesn't match?

I need (in PHP) to split a sententse by the word that cannot be the first or the last one in the sentence. Say the word is "pression" and here is my regex
/^.+?(?=[\s\.\,\:\;])pression(?=[\s\.\,\:\;]).+$/i
Live here: https://regex101.com/r/CHAhKj/1/
First, it doesn't match.
Next, I think - it is at all possible to split that way? I tryed simplified example
print_r(preg_split('/^.+pizza.+$/', 'my pizza is cool'));
live here http://sandbox.onlinephpfunctions.com/code/10b674900fc1ef44ec79bfaf80e83fe1f4248d02
and it prints an array of 2 empty strings, when I expect
['my ', ' is cool']
I need (in PHP) to split a sentence by the word that cannot be the first or the last one in the sentence
You may use this regex:
(?<=[^\s.?]\h)pression(?=\h[^\s.?])
RegEx Demo
RegEx Details:
(?<=[^\s.?]\h): Lookbehind to assert that ahead of current position we have a space and a character that not a whitespace, not a dot and not a ?.
pression: Match word pression
(?=\h[^\s.?]): Lookahead to assert that before current position we have a space and a character that not a whitespace, not a dot and not a ?
First, ^.+?(?=[\s\.\,\:\;])pression(?=[\s\.\,\:\;]).+$ can't match any string at all because the (?=[\s\.\,\:\;])p part requires p to be also either a whitespace char, or a ., ,, : or ;, which invalidates the whole match at once.
Second, ^.+pizza.+$ pattern does not ensure the pizza matched is not the first or last word in a sentence as . matches whitespace, too. It does not return anything meaningful, because preg_split uses the match to break string into chunks, and the two empty values are 1) start of string and 2) empty string positions.
That said, all you need is:
preg_match('~^(.*?\w\W+)pression(\W+\w.*)$~is', $text, $m)
See the regex demo. Details:
^ - start of string
(.*?\w\W+) - Capturing group 1: any zero or more chars, as few as possible, then a word char and then one or more non-word chars
pression - a word
(\W+\w.*) - Capturing group 2: one or more non-word chars, a word char, and then any zero or more chars as many as possible
$ - end of string.
s makes the . match across lines and i flag makes the pattern match in a case insensitive way.
See the PHP demo:
$text = "You can use any regular expression pression inside the lookahead ";
if (preg_match('~^(.*?\w\W+)pression(\W+\w.*)$~is', $text, $m)) {
echo $m[1] . " << | >> " . $m[2];
}
// => You can use any regular expression << | >> inside the lookahead

How can I split a string by white spaces that are not precedent by a certain character?

I want to split a string only at white spaces that does not have a certain delimiter (: in my case) before it. E.g.:
$string = "Time: 10:40 Request: page.php Action: whatever this is Refer: Facebook";
Then from something like this I want to achieve an array such that:
$array = ["Time: 10:40", "Request: page.php", "Action: whatever this is", "Refer: Facebook"];
I've tried the following so far:
$split = preg_split('/(:){0}\s/', $visit);
But this is still splitting at every occurence of a white space.
Edit: I think I asked the wrong question, however "whatever this is" should stay as a single string
Edit 2: The bits before the colons are known and stay the same, maybe incorporating those somehow makes the task easier (of not splitting at whitespace characters in strings that should stay together)?
You can use a lookahead in your split regex:
/\h+(?=[A-Z][a-z]*: )/
RegEx Demo
Regex \h+(?=[A-Z][a-z]*: ) matches 1+ whitespaces that is followed by a word starting with upper case letter and a colon and space.
you can do it
$string = "Time: 10:40 Request: page.php Action: whatever this is Refer: Facebook";
$split = preg_split('/\h+(?=[A-Z][a-z]*:)/', $string);
dd($split);
Another option could be to match what is before the colon and then match upon the next part that starts with a space, non whitespace chars and colon:
\S+:\h+.*?(?=\h+\S+:)\K\h+
\S+: Match 1+ times a non whitespace char
\h+ Match 1+ times a horizontal whitespace char
.*? Match any char except a newline non greedy
(?=\h+\S+:) Positive lookahead, assert what is on the right is 1+ horizontal whitespace chars, 1+ non whitespace chars and a colon
\K\h+ Forget what was matched using \K and match 1+ horizontal whitespace chars
Regex demo | php demo

Regex to match numbers only if alphabets are present

I require a regex to match the string in the following way:
#1234abc : Should get matched
#abc123 : Should get matched
#123abc123 : Should get matched
#123 : Should not get matched
#123_ : Should not get matched
#123abc_ : Should get matched
This implies that it should only get matched if the string contains numbers or underscore along with alphabets. Only numbers/underscore should not get matched. Any other special characters should not get matched either.
This regex is basically to get hashtags from string. I have already tried the following but it didn't worked well for me.
preg_match_all('/(?:^|\s)#([a-zA-Z0-9_]+$)/', $text, $matches);
Please suggest something.
If you need to match hashtags in the format you specified in a larger string, use
(?<!\S)#\w*[a-zA-Z]\w*
See the regex demo
Details:
(?<!\S) - there must be a start of string or a whitespace before
# - a hash symbol
\w* - 0+ word chars (that is, letters, digits or underscore)
[a-zA-Z] - a letter (you may use \p{L} instead)
\w* - 0+ word chars.
Other alternatives (that may appear faster, but are a bit more complex):
(?<!\S)#(?![0-9_]+\b)\w+
(?<!\S)#(?=\w*[a-zA-Z])\w+
The point here is that the pattern basically matches 1+ word chars preceded with # that is either at the string start or after whitespace, but (?![0-9_]+\b) negative lookahead fails all matches where the part after # is all digits/underscores, and the (?=\w*[a-zA-Z]) positive lookahead requires that there should be at least 1 ASCII letter after 0+ word chars.
You can use this Regex:
((.*?(\d+)[a-zA-Z]+.*)|(.*[a-zA-Z]+(\d+).*)).
Access it here: http://regexr.com/3ef6q
see it working:
Do:
^(?=.*[A-Za-z])[\w_]+$
[\w_]+ matches one or more of letters, digits, _
The zero width positive lookahead pattern, (?=.*[A-Za-z]), makes sure the match contains at least one letter
Demo

My php checkRE function shows the answer right but I think it is wrong

The RegEx is [\w|\W]*\s[\w|\W]* and the string is aaab# asd123 because I think [\w|\W]* is equal to \w*|\W* which means multiple of words character or non-words character... how can it have both word and non-word character together like aab# ?
NOTE: Your string appears to be space delimited, so you could just use explode(" ", $s). The answer below is to just explain how regex works.
I believe you misunderstood the [\w|\W]* and \w*|\W*: the first one matches any 0+ characters, and the second one matches either 0+ word chars or 0+ non-word chars.
You seem to want to match 0+ non-whitespace characters, use \S+:
\S+\s+\S+
Or, to capture the two non-whitespace parts:
(\S+)\s+(\S+)
The + will make the pattern match one or more occurrences of a non-whitespace pattern at a stretch.
See the regex demo

REGEX - match words that contain letters repeating next to each other

im looking for a regex that matches words that repeat a letter(s) more than once and that are next to each other.
Here's an example:
This is an exxxmaple oooonnnnllllyyyyy!
By far I havent found anything that can exactly match:
exxxmaple and oooonnnnllllyyyyy
I need to find it and place them in an array, like this:
preg_match_all('/\b(???)\b/', $str, $arr) );
Can somebody explain what regexp i have to use?
You can use a very simple regex like
\S*(\w)(?=\1+)\S*
See how the regex matches at http://regex101.com/r/rF3pR7/3
\S matches anything other than a space
* quantifier, zero or more occurance of \S
(\w) matches a single character, captures in \1
(?=\1+) postive look ahead. Asserts that the captrued character is followed by itsef \1
+ quantifiers, one or more occurence of the repeated character
\S* matches anything other than space
EDIT
If the repeating must be more than once, a slight modification of the regex would do the trick
\S*(\w)(?=\1{2,})\S*
for example http://regex101.com/r/rF3pR7/5
Use this if you want discard words like apple etc .
\b\w*(\w)(?=\1\1+)\w*\b
or
\b(?=[^\s]*(\w)\1\1+)\w+\b
Try this.See demo.
http://regex101.com/r/kP8uF5/20
http://regex101.com/r/kP8uF5/21
You can use this pattern:
\b\w*?(\w)\1{2}\w*
The \w class and the word-boundary \b limit the search to words. Note that the word boundary can be removed, however, it reduces the number of steps to obtain a match (as the lazy quantifier). Note too, that if you are looking for words (in the common meaning), you need to remove the word boundary and to use [a-zA-Z] instead of \w.
(\w)\1{2} checks if a repeated character is present. A word character is captured in group 1 and must be followed with the content of the capture group (the backreference \1).

Categories