php - find match in string - php

I'm trying to work out how to find a match in a string.
I'm looking for a match on any of the following - = ? [] ~ # ! 0 - 9 A-Z a-z and I need to know what its matched on .
Eg: matched on !, or matched on = and # and ?
Normally I'd use this:
$a = 'How are you?';
if (strpos($a, 'are') !== false) {
echo 'true';
}
However I'm not sure how to do that so it looks up the characters needed.
Also where I may have [], It could be [] or [xxxx] where xxxx could be any number of alpha numeric characters.
I need to match and any of the characters listed, return the characters so I know what was matched and if the [] contain any value return that as well.
Eg:
$a = 'DeviceLocation[West12]';
Would return: $match = '[]'; $match_val= 'West12';
$a = '#=Device';
Would return:$match = '#,=';
$a= '?[1234]=#Martin';
Would return: $match = '?, [], =, #'; $match_val= '1234';
Can any one advise how I can do this.
Thanks

Well, that requirements are a bit vague, but that is what I deduced:
1) if there is an alphanumeric string inside square brackets get it as a separate value
2) all other mentioned chars should be matched one by one and then imploded.
You may use the following regex to get the values you need:
$re = '#\[([a-zA-Z0-9]+)\]|[][=?~#!]#';
Details:
\[ - a [
([a-zA-Z0-9]+) - Group 1 value capturing 1 or more alphanumeric symbols
\] - a closing ]
| - or
[][=?~#!] - a single char, one of the defined chars in the set.
See the regex demo. The most important here is the code that gets the matches (feel free to adapt):
$re = '#\[([a-zA-Z0-9]+)\]|[][=?~#!]#';
$strs =array('DeviceLocation[West12]', '#=Device', '?[1234]=#Martin');
foreach ($strs as $str) {
preg_match_all($re, $str, $matches, PREG_SET_ORDER);
$results = array();
$match_val = "";
foreach ($matches as $m) {
if (!empty($m[1])) {
$match_val = trim($m[1], "[]");
array_push($results, "[]");
} else {
array_push($results, $m[0]);
}
}
echo "Value: " . $match_val . "\n";
echo "Symbols: " . implode(", ", $results);
echo "\n-----\n";
}
See the PHP demo
Output:
Value: West12
Symbols: []
-----
Value:
Symbols: #, =
-----
Value: 1234
Symbols: ?, [], =, #
-----

Please use Regular Expressions, e.g using preg_match

Try this
It will match the string in []
preg_match_all("/\[([^\]]*)\]/", $text, $matches);
And this will match string after ? and #=
preg_match_all("/^#=(\S+)|\?(.*)/", $text, $matches);
var_dump($matches);

You need regular expressions to check for any text inside another with different properties, here is a simple tutorial on that link.

Related

How to match String in foreach loop with preg_split in PHP

I have data with 2 parts with this separator |
$data = 'hello | Hello there
price | Lets talk about our support.
how are you ?| Im fine ';
And my static word is $word= 'price'
My code
$msg = array_filter(array_map('trim', explode("\n", $data)));
foreach ($msg as $singleLine) {
$partition = preg_split("/[|]+/", trim($singleLine), '2');
$part1 = strtolower($partition[0]);
}
How can I match the data? I need the result to be like this: Let's talk about our support
You may use a single regex approach:
'~^\h*price\h*\|\h*\K.*\S~m'
See the regex demo
Details
^ - start of a line (due to m modifier)
\h* - 0+ horizontal whitespace
price - your static word
\h*\|\h* - | enclosed with 0+ horizontal whitespaces
\K - match reset operator that discards the text matched so far
.*\S - 0+ chars other than line break chars, as many as possible, up to the last non-whitespace char on the line (including it).
PHP code:
if (preg_match('~^\h*' . preg_quote($word, '~') . '\h*\|\h*\K.*\S~m', $data, $match)) {
echo $match[0];
}
Wiktor's answer seems good, but you might want to turn your data into a key -> value array.
If that is the case, you may do this:
$avp = [];
if (preg_match_all('/^ \h* (?<key>[^|]+?) \h* \| \h* (?<value>[^$]+?) \h* $/mx', $data, $matches, PREG_SET_ORDER)) {
foreach ($matches as [, $key, $value]) {
$avp[$key] = $value;
}
}
$word = 'price';
echo $avp[$word]; // Lets talk about our support.
Demo: https://3v4l.org/uMBAg

How do I get number from this format:,[[5,["95",1,"#ffffff"]]]], using regex

I have a string like this:
",[[3,"bus.png",null,"Bus",[["https://maps.gstatic.com/mapfiles/transit/iw2/b/bus.png",0,[15,15],null,0]]]],[[null,null,null,null,"0x31da18325b415901:0xeb661015c651c24a",[[5,["48",1,"#ffffff"]]]],[null,null,null,null,"0x31da19f34e04d59b:0x5758ef6990938b",[[5,["61",1,"#ffffff"]]]],[null,null,null,null,"0x31da1a5b8b75c379:0x6a13e189555f9fab",[[5,["95",1,"#ffffff"]]]],[null,null,null,null,"0x31da1a16ea23bf95:0xd7c90f15535c2b9f",[[5,["106",1,"#ffffff"]]]],[null,null,null,null,"0x31da10a7613d616f:0xf1f61ffeac2ea8a4",[[5,["970",1,"#ffffff"]]]],[null,null,null,null,"0x31da1a0bd6262d0b:0xfbd5d2bfd7a1252",[[5,["NR8",1,"#ffffff"]]]]],null,0,"5"]]],["http://www
I need to get all the numbers: "48, 61,95,106,970,NR8"; so basically, need to process this format :"48, 61,95,106,970,NR8"
I tried:
function get_numbers_from($input) {
$matches = preg_match_all('(\[\"[]a-zA-Z0-9]*?\"\,\d*?\,\".*?\"\])', $input);
foreach($matches[1] as $key => $match) {
array_push($numbers, explode(',', $match)[0]);
}
return $numbers;
}
But seems it shows: Invalid argument supplied for foreach()
How to correct it?
Check the manual for preg_match_all(), the function returns a boolean. And you use the third parameter for the matches.
Also you can change your regex to this one:
\[\[\d+,\[\"(\w+)\",\d+,"#[\da-fA-F]+"]]]]
To get the number directly from it without explode(), e.g.
function get_numbers_from($input) {
preg_match_all('/\[\[\d+,\[\"(\w+)\",\d+,"#[\da-fA-F]+"]]]]/', $input, $matches);
return $matches[1];
}
You can use
'~\["([A-Z]*\d+)"~'
See the regex demo and the IDEONE demo
$re = '~\["([A-Z]*\d+)"~';
$str = "\",[[3,\"bus.png\",null,\"Bus\",[[\"https://maps.gstatic.com/mapfiles/transit/iw2/b/bus.png\",0,[15,15],null,0]]]],[[null,null,null,null,\"0x31da18325b415901:0xeb661015c651c24a\",[[5,[\"48\",1,\"#ffffff\"]]]],[null,null,null,null,\"0x31da19f34e04d59b:0x5758ef6990938b\",[[5,[\"61\",1,\"#ffffff\"]]]],[null,null,null,null,\"0x31da1a5b8b75c379:0x6a13e189555f9fab\",[[5,[\"95\",1,\"#ffffff\"]]]],[null,null,null,null,\"0x31da1a16ea23bf95:0xd7c90f15535c2b9f\",[[5,[\"106\",1,\"#ffffff\"]]]],[null,null,null,null,\"0x31da10a7613d616f:0xf1f61ffeac2ea8a4\",[[5,[\"970\",1,\"#ffffff\"]]]],[null,null,null,null,\"0x31da1a0bd6262d0b:0xfbd5d2bfd7a1252\",[[5,[\"NR8\",1,\"#ffffff\"]]]]],null,0,\"5\"]]],[\"http://www\n48, 61,95,106,970,NR8";
preg_match_all($re, $str, $matches);
print_r($matches[1]);
The pattern matches:
\[ - a [
" - a quote
([A-Z]*\d+) - Group 1: any uppercase ASCII letter, 0 or more times, followed with 1 or more digits
" - a quote
The value you need is located inside the $matches[1] variable. It holds all the values captured with the parenthesized subpattern (Group 1).

extracting data between [ ] with preg_match php

i try to extract only the number beetween the [] from my response textfile:
$res1 = "MESSAGE_RESOURCE_CREATED Resource [realestate] with id [75739528] has been created.";
i use this code
$regex = '/\[(.*)\]/s';
preg_match($regex, $res1, $matches_arr);
echo $matches_arr[1];
my result is:
realestate] with id [75742084
Can someone help me ?
Use this:
$regex = '~\[\K\d+~';
if (preg_match($regex, $res1 , $m)) {
$thematch = $m[0];
// matches 75739528
}
See the match in the Regex Demo.
Explanation
\[ matches the opening bracket
The \K tells the engine to drop what was matched so far from the final match it returns
\d+ matches one or more digits
I assume you want to match what's inside the brackets, which means that you must match everything but a closing bracket:
/\[([^]]+)\]/g
DEMO HERE
Omit the g-flag in preg_match():
$regex = '/\[([^]]+)\]/';
preg_match($regex, $res1, $matches_arr);
echo $matches_arr[1]; //will output realestate
echo $matches_arr[2]; //will output 75739528
Your regex would be,
(?<=\[)\d+(?=\])
DEMO
PHP code would be,
$regex = '~(?<=\[)\d+(?=\])~';
preg_match($regex, $res1, $matches_arr);
echo $matches_arr[0];
Output:
75739528

regex for matching three specific character

while attempting a question in SO,i tried to write the regular expression which matches three characters that should be in the string.
i am following the answer Regular Expressions: Is there an AND operator?
<?php
$words = "systematic,gear,synthesis,mysterious";
$words=explode(",",$words);
$your_array = preg_grep("/^(^s|^m|^e)/", $words);
print_r($your_array);
?>
the output should be systematic and mysterious.but i am getting synthesis also.
Why is it so?what i am doing wrong?
** i dont want a new solution :)
SEE HERE
You can do this:
$wordlist = 'systematic,gear,synthesis,mysterious';
$words = explode(',', $wordlist);
foreach($words as $word) {
if (preg_match('~(?=[^s]*s)(?=[^m]*m)(?=[^e]*e)~', $word))
echo '<br/>' . $word;
}
//or
$res = preg_grep('~(?=[^s]*s)(?=[^m]*m)(?=[^e]*e)~', $words);
print_r($res);
To test the presence of a character in the string, I use (?=[^s]*s).
[^s]*s means all that is not a "s" zero or more times, and a "s".
(?=..) is a lookahead assertion and means "followed by". It is only a check, a lookahead give no characters in a match result, but the main interest with this feature is that you can check the same substring several times.
What is wrong with your pattern?
/^(^s|^m|^e)/ will give you only words that begins with "s" or "m" or "e" because ^ is an anchor and means : "start of the string". In other words, your pattern is the same as /^([sme])/.

Regex: Using capture data further in the regex

I want to parse some text that start with ":" and could be surround with parentheses to stop the match so:
"abcd:(someText)efgh" and
"abcd:someText"
will return someText.
but i have a problem to set the parentheses optionnal.
I make this but it does not works:
$reg = '#:([\\(]){0,1}([a-z]+)$1#i';
$v = 'abc:(someText)def';
var_dump(preg_match($reg,$v,$matches));
var_dump($matches);
The $1 makes it failed.
i don't know how to tell him :
If there is a "(" at the beginning, there must be ")" at the end.
You can't test if the count of something is equal to another count. It's a regex problem who can only be used with regular language (http://en.wikipedia.org/wiki/Regular_language). To achieve your goal, as you asked - and that is if there's a '(' should be a ')' -, you'll need a Context-Free Language (http://en.wikipedia.org/wiki/Context-free_language).
Anyway, you can use this regex:
'/:(\([a-z]+\)|[a-z]+)/i
To return the match of different sub-patterns in the regex to the same element of the $matches array, you can use named subpattern with the internal option J to allow duplicate names. The return element in $matches is the same as the name of the pattern:
$pattern = '~(?J:.+:\((?<text>[^)]+)\).*|.+:(?<text>.+))~';
$texts = array(
'abc:(someText)def',
'abc:someText'
);
foreach($texts as $text)
{
preg_match($pattern, $text, $matches);
echo $text, ' -> ', $matches['text'], '<br>';
}
Result:
abc:(someText)def -> someText
abc:someText -> someText
Demo
This regex will match either :word or :(word) groups 1 and 2 hold the respective results.
if (preg_match('/:([a-z]+)|\(([a-z]+)\)/i', $subject, $regs)) {
$result = ($regs[1])?$regs[1]:$regs[2];
} else {
$result = "";
}
regex: with look-behind
"(?<=:\(|:)[^()]+"
test with grep:
kent$ echo "abcd:(someText)efgh
dquote> abcd:someOtherText"|grep -Po "(?<=:\(|:)[^()]+"
someText
someOtherText
Try this
.+:\((.+)\).*|.+:(.+)
if $1 is empty there are no parentheses and $2 has your text.

Categories