PHP/REGEX: Get a string within parentheses - php

This is a really simple problem, but I couldn't find a solution anywhere.
I'm try to use preg_match or preg_match_all to obtain a string from within parentheses, but without the parentheses.
So far, my expression looks like this:
\([A-Za-z0-9 ]+\)
and returns the following result:
3(hollow highlight) 928-129 (<- original string)
(hollow highlight) (<- result)
What i want is the string within parentheses, but without the parentheses. It would look like this:
hollow highlight
I could probably replace the parentheses afterwards with str_replace or something, but that doesn't seem to be a very elegant solution to me.
What do I have to add, so the parentheses aren't included in the result?
Thanks for your help, you guys are great! :)

try:
preg_match('/\((.*?)\)/', $s, $a);
output:
Array
(
[0] => (hollow highlight)
[1] => hollow highlight
)

You just need to add capturing parenthesis, in addition to your escaped parenthesis.
<?php
$in = "hello (world), my name (is andrew) and my number is (845) 235-0184";
preg_match_all('/\(([A-Za-z0-9 ]+?)\)/', $in, $out);
print_r($out[1]);
?>
This outputs:
Array ( [0] => world [1] => is andrew [2] => 845 )

Related

regex - finding multiple occurances of a pattern and extracting a string [duplicate]

I have tried the non capturing group option ?:
Here is my data:
hello:"abcdefg"},"other stuff
Here is my regex:
/hello:"(.*?)"}/
Here is what it returns:
Array
(
[0] => Array
(
[0] => hello:"abcdefg"}
)
[1] => Array
(
[0] => abcdefg
)
)
I wonder, how can I make it so that [0] => abdefg and that [1] => doesnt exist?
Is there any way to do this? I feel like it would be much cleaner and improve my performance. I understand that regex is simply doing what I told it to do, that is showing me the whole string that it found, and the group inside the string. But how can I make it only return abcdefg, and nothing more? Is this possible to do?
Thanks.
EDIT: I am using the regex on a website that says it uses perl regex. I am not actually using the perl interpreter
EDIT Again: apparently I misread the website. It is indeed using PHP, and it is calling it with this function: preg_match_all('/hello:"(.*?)"}/', 'hello:"abcdefg"},"other stuff', $arr, PREG_PATTERN_ORDER);
I apologize for this error, I fixed the tags.
EDIT Again 2: This is the website http://www.solmetra.com/scripts/regex/index.php
preg_match_all
If you want a different captured string, you need to change your regex. Here I'm looking for anything not a double quote " between two quote " characters behind a : colon character.
<?php
$string = 'hello:"abcdefg"},"other stuff';
$pattern = '!(?<=:")[^"]+(?=")!';
preg_match_all($pattern,$string,$matches);
echo $matches[0][0];
?>
Output
abcdefg
If you were to print_r($matches) you would see that you have the default array and the matches in their own additional arrays. So to access the string you would need to use $matches[0][0] which provides the two keys to access the data. But you're always going to have to deal with arrays when you're using preg_match_all.
Array
(
[0] => Array
(
[0] => abcdefg
)
)
preg_replace
Alternatively, if you were to use preg_replace instead, you could replace all of the contents of the string except for your capture group, and then you wouldn't need to deal with arrays (but you need to know a little more about regex).
<?php
$string = 'hello:"abcdefg"},"other stuff';
$pattern = '!^[^:]+:"([^"]+)".+$!s';
$new_string = preg_replace($pattern,"$1",$string);
echo $new_string;
?>
Output
abcdefg
preg_match_all is returning exactly what is supposed to.
The first element is the entire string that matched the regex. Every other element are the capture groups.
If you just want the the capture group, then just ignore the 1st element.
preg_match_all('/hello:"(.*?)"}/', 'hello:"abcdefg"},"other stuff', $arr, PREG_PATTERN_ORDER);
$firstMatch = $arr[1];

Is there a method to omit nested parentheses in regex?

I'm writing a regex function for PHPs' preg_match_all to find all ifs(...) with all its contents from a string. (In my example I've got only one ifs, as it's not re root of the problem.)
Here's what I've got so far:
Pattern: /ifs\(.*?\)/i
String: =iferror(ifs(OR("foo", "bar"),"a",OR("tar", "scar"),"b",OR("lar"),"d"),"c")
Current output: ifs(OR("foo", "bar")
Expected output: ifs(OR("foo", "bar"),"a",OR("tar", "scar"),"b",OR("lar"),"d")
The problem: regex finds first closing parentheses.
Where am I going wrong? And how would you tackle nested parentheses?
Demo: https://regex101.com/r/SgBqbW/1
Actually you can do this thanks to PHPs capability of recursive regexps. This is inspired by this comment on that page:
$string = '=iferror(ifs(OR("foo", "bar"),"a",OR("tar", OR("scar", "baa")),"b",OR("lar"),"d"),"c")
blah blah ifs(OR("foo", "bar"),"a") and another one ifs("a", OR("tar", OR("scar", "baa")),"b",OR("lar"),"d")';
$regex = '/ifs(\(((?>[^()]+)|(?-2))*\))/';
preg_match_all($regex, $string, $matches);
print_r($matches[0]);
Output:
Array (
[0] => ifs(OR("foo", "bar"),"a",OR("tar", OR("scar", "baa")),"b",OR("lar"),"d")
[1] => ifs(OR("foo", "bar"),"a")
[2] => ifs("a", OR("tar", OR("scar", "baa")),"b",OR("lar"),"d")
)
Demo on 3v4l.org

Split string into words in php

I want to split string which contains braces
e.g.
string = "some-thing_text,text in rounded brackets(word first,word second),Text in curly brackets{some-text(some one,some two),some another},Text in square brackets[some text,some another{some like this(this1,this2)}]"
and output will be :
Array
(
[0] => some-thing_text
[1] => text in rounded brackets(word first,word second)
[2] => Text in curly brackets{some-text(some one,some two),some another}
[3] => Text in square brackets[some text,some another{some like this(this1,this2)}]
)
,(?![^{]*})(?![^(]*\))(?![^\[]*\])
You can use this.See demo.
https://regex101.com/r/lR1eC9/8
You may try this,
preg_split('~(?:\[.*?\]|\(.*?\)|\{.*?\})(*SKIP)(*F)|,~', $str);
(?:\[.*?\]|\(.*?\)|\{.*?\}) matches all the bracketed blocks.
(*SKIP)(*F) makes the previous match to fail.
, Now it matches comma from the remaining string.
DEMO
preg_split('~,(?![^{]*}|[^(]*\)|[^\[]*\])~', $string)

PHP regex, how can I make my regex only return one group?

I have tried the non capturing group option ?:
Here is my data:
hello:"abcdefg"},"other stuff
Here is my regex:
/hello:"(.*?)"}/
Here is what it returns:
Array
(
[0] => Array
(
[0] => hello:"abcdefg"}
)
[1] => Array
(
[0] => abcdefg
)
)
I wonder, how can I make it so that [0] => abdefg and that [1] => doesnt exist?
Is there any way to do this? I feel like it would be much cleaner and improve my performance. I understand that regex is simply doing what I told it to do, that is showing me the whole string that it found, and the group inside the string. But how can I make it only return abcdefg, and nothing more? Is this possible to do?
Thanks.
EDIT: I am using the regex on a website that says it uses perl regex. I am not actually using the perl interpreter
EDIT Again: apparently I misread the website. It is indeed using PHP, and it is calling it with this function: preg_match_all('/hello:"(.*?)"}/', 'hello:"abcdefg"},"other stuff', $arr, PREG_PATTERN_ORDER);
I apologize for this error, I fixed the tags.
EDIT Again 2: This is the website http://www.solmetra.com/scripts/regex/index.php
preg_match_all
If you want a different captured string, you need to change your regex. Here I'm looking for anything not a double quote " between two quote " characters behind a : colon character.
<?php
$string = 'hello:"abcdefg"},"other stuff';
$pattern = '!(?<=:")[^"]+(?=")!';
preg_match_all($pattern,$string,$matches);
echo $matches[0][0];
?>
Output
abcdefg
If you were to print_r($matches) you would see that you have the default array and the matches in their own additional arrays. So to access the string you would need to use $matches[0][0] which provides the two keys to access the data. But you're always going to have to deal with arrays when you're using preg_match_all.
Array
(
[0] => Array
(
[0] => abcdefg
)
)
preg_replace
Alternatively, if you were to use preg_replace instead, you could replace all of the contents of the string except for your capture group, and then you wouldn't need to deal with arrays (but you need to know a little more about regex).
<?php
$string = 'hello:"abcdefg"},"other stuff';
$pattern = '!^[^:]+:"([^"]+)".+$!s';
$new_string = preg_replace($pattern,"$1",$string);
echo $new_string;
?>
Output
abcdefg
preg_match_all is returning exactly what is supposed to.
The first element is the entire string that matched the regex. Every other element are the capture groups.
If you just want the the capture group, then just ignore the 1st element.
preg_match_all('/hello:"(.*?)"}/', 'hello:"abcdefg"},"other stuff', $arr, PREG_PATTERN_ORDER);
$firstMatch = $arr[1];

Why doesn't this PHP regular expression extract the url from the css value?

I want to extract the url from the background css property "url('/img/hw (11).jpg') no-repeat". I tried:
$re = '/url\(([\'\"]?.*\.[png|jpg|jpeg|gif][\'\"]?)\)/i';
$text = "url('/img/hw (11).jpg')";
preg_match_all($re, $text, $matches);
print_r($matches);
and it gives me :
Array
(
[0] => Array
(
)
[1] => Array
(
)
)
Here is the correct regex. The ".*" in the middle of your regex is too greedy. Also, try replacing the square brackets with paranthesis. Also note that since you are using single quotes around the string that you do not need to escape the double quotes.
$re = '/url\(([\'"]?.[^\'"]*\.(png|jpg|jpeg|gif)[\'"]?)\)/i';
Try:
/url\(([\'\"]?.*\.(png|jpg|jpeg|gif)[\'\"]?)\)/i
Instead. The square brackets do a character-by-character comparison rather than the or comparison you're looking for.
I think the probably lies in this part [png|jpg|jpeg|gif]. It's supposed to match only single characters.
You should do this instead :
/url\([\'\"]?(.*\.(jpg|png|jpeg|gif)[\'\"]?)\)/

Categories