PHP regular expression : match the closest one - php

I have a string like this
<div><span style="">toto</span> some character <span>toto2</span></div>
My regex:
/(<span .*>)(.*)(<\/span>)/
I used preg_match and it returns the entire string
<span style="">toto</span> some character <span>toto2</span>
I want it returns:
<span style="">toto</span>
and
<span>toto2</span>
What do I need to do to achieve this? Thanks.

How about this:
/(<span[^>]*>)(.*?)(<\/span>)/
Check the docs here at PHP preg_match Repetition:
By default, the quantifiers are "greedy", that is, they match as much as possible
and
However, if a quantifier is followed by a question mark, then it becomes lazy, and instead matches the minimum number of times possible

Even though I guess all previous answers are correct, I just want to add that as you only want to capture the whole expressions (i.e. from to ) you don't have to capture eveything inside the regexp with ()
The following does what you expect without capturing additional expressions
/(<span\w*[^>]*>[^<]*<\/span>)/
(tested on http://rubular.com/)
EDIT : of course there might be some differences between PHP and ruby regexp implementations, but the idea is the same :)

Related

regex and preg_replace_callback

I have a problem with a regular expression.
I'm working with tokens and I have to parse a text like this:
Just some random text
#IT=AB|First statement# #xxxx=xxx|First statement|Second statement#
More text
I use preg_replace_callback since I have to use the first statement or the second one, depending on the first expression is true or not; it's a sort of IF...ELSE... statement.
What I expect are 2 elements like this:
#IT=AB|First statement#
#xxxx=xxx|First statement|Second statement#
So I can start manipulating them inside my callback function.
I tried with this regex /#.*#/, but i get the entire string, it's not parsed into elements.
How can I achieve that? I'm sorry but regex aren't my thing :(
The quantifier * is greedy by default. So a .* will match as much as it can and as a result it'll match a # as well. To fix this you can make the * non-greedy by adding a ? after it. Now a .*? will try to much as little as it can.
/#.*?#/
or you can look for only non # characters between two #:
/#[^#]*#/

Regex to find function call php

I need the regex to find function calls in strings in php, I have tried to search here on stackoverflow but none of the ones i've tried worked.
this pattern: ^.*([\w][\(].*[\)])
This will match: functionone(fgfg) but also functionone(fgfg) dhgfghfgh functiontwo() as one match. Not 2 separate matches (as in functionone(fgfg) and functiontwo().
I don't know how to write it but I think this is what I need.
1. Any string, followed by (
2. Any string followed by )
And then it should stop, not continue. Any regex-gurus that can help me out?
I see 5 issues with your regex
If you want to match 2 functions in the same row, don't use the anchor ^, this will anchor the regex to the start of the string.
You then don't need .* at the start maybe more something like \w+ (I am not sure what the spec of a function name in PHP is)
if there is only one entry in a character class (and its not a negated one), you don't need the character class
The quantifier between the brackets needs to be a lazy one (followed by a ?). So after this 4 points your regex would look something like
\w+\(.*?\)
Is a regex really the right tool for this job?
Don't use regexp for this... use PHP's built-in tokenizer
A function signature is not a regular language. As such, you cannot use a regular expression to match a function signature. Your current regex will match signatures that are NOT valid function signatures.
What I would suggest you use is the PHP tokenizer.

Convert PHP RegEx to JavaScript RegEx

I have a PHP regular expression I'm using to get the YouTube video code out of a URL.
I'd love to match this with a client-side regular expression in JavaScript. Can anyone tell me how to convert the following PHP regex to JavaScript?
preg_match("#(?<=v=)[a-zA-Z0-9-]+(?=&)|(?<=v\/)[^&\n]+(?=\?)|(?<=embed/)[^&\n]+|(?<=v=)[^&\n]+|(?<=youtu.be/)[^&\‌​n]+#", $url, $matches);
Much appreciated, thanks!
I think the only problem is to get rid of the lookbehind assertions (?<=...), they are not supported in Javascript.
The advantage of them is, you can use them to ensure that a pattern is before something, but they are NOT included in the match.
So, you need to remove them, means change (?<=v=)[a-zA-Z0-9-]+(?=&) to v=[a-zA-Z0-9-]+(?=&), but now your match starts with "v=".
If you just need to validate and don't need the matched part, then its fine, you are done.
But if you need the part after v= then put instead the needed pattern into a capturing group and continue working with those captured values.
v=([a-zA-Z0-9-]+)(?=&)
You will then find the matched substring in $1 for the first group, $2 for the second, $3 ...
you can replace your look behind assertion using this post
Javascript: negative lookbehind equivalent?

Capturing a pattern of unknown repitition in PCRE

This may be a quick question for experienced regular expressionists, but I'm having trouble getting my match to execute correctly.
Suppose I had a string that looked like this:
http://aaa-bbbb-cc-ddddd-eee-.sub.dom
I would like to go capture all of the "aaa", "bbbb", "cc", and "ddddd" substrings, but I'm not sure how many there will be (e.g., having all triplets up through "zzz").
This is the regular expression I'm trying to use right now:
/http:\/\/(\w*?\-)+\.sub\.dom/
I wrote it this way because:
I want to match substrings, but I want each to terminate when a - is parsed
I want to capture one or more of these substrings
But it seems to only be saving the last match that it makes (in the above case, it would only match "eee-".
Is there a good way to capture all of the matched substrings?
More information: I'm using PHP's PCRE function preg_replace_callback. Thanks!
No, it is not possible to match an unknown number of capture groups.
If you try to repeat a capture group, it will always contain the last value captured.
Could you explain a bit more broadly what you're trying to do? Perhaps there is another simple way to do it (possibly without regular expressions).
If you want the items in the subdomain, and then all matches between the dashes... This should work:
$string = "http://aaa-bbbb-cc-ddddd-eee-.sub.dom";
preg_match("/^http:\/\/([\w-]+?)\..*$/i", $string, $match);
$parts = explode('-', $match[1]);
print_r($parts);
Short of that you will probably have to build a small parsing script to parse the string yourself if that doesn't do it for you.

Stop a regex matching *everything* after what I want to actually match! [duplicate]

This question already has answers here:
My regex is matching too much. How do I make it stop? [duplicate]
(5 answers)
Closed 3 years ago.
I am quite new to the whole Regex thing and tried to do a preg_match_all in PHP which, kind of the results I wanted but the problem is it matches everything after what I actually wanted... like so:
String: This is something <code>Some code here</code> and more
Match from Regex: <code>Some code here</code> and more
Wanted match from Regex: <code>Some code here</code>
Here is my regular expression that I'm using:
/<code>(.*)<\/code>/
I think its something to do with the beginning and ending / delimiters but I'm not entirely sure.
Any help would be appreciated, thanks!
The star is greedy, meaning it will match as much as it can. Use
(.*?)
instead, making it lazy. You can also use negated character classes:
!<code>([^<]*)</code>!
EDIT: Since mvds deleted his/her answer, here's a tip: You can avoid having to escape the slash (/) if you don't use it as a delimiter, like I did above ^ (used ! )
Here's a good resource on regex:
http://www.regular-expressions.info/repeat.html
you want to make the .* be non greedy. If you put a ? after that part of the pattern it will match everything up to the next part of the regex that matches. So make the regex /<code>(.*?)<\/code>/
You need to disable greediness. Use .*? instead, I believe.
I'm not 100% sure how this is even compiling - you need to escape the second / as so:
/<code>(.*)<\/code>/
So that PHP recognises it as a character to match rather than the end of the regular expression (I think it may be compiling as a substitute regex).

Categories