2

I have a string that looks like this

Hello, my name is "{{ @sql(SELECT TOP 1 name FROM table1 WHERE [id] = 5 ) }}" and my title is "{{ @sql(SELECT TOP 1 title FROM table1 WHERE [id] = 5 ) }}"

I need to be able to take this string and parse out any pattern that matches the following pattern {{ @sql(WHATEVER QUERY GOES HERE) }} it must start with two braken followed by optional spaces and then @sql( ending in ) }}

Additionally, I will also need to extract the inner query which is the text that is found between @sql( and ending in ) }} Here is what I have done

$pattern = '/\{\{\s*+@sql\((.+)\)+\s*+\}\}/i';

$matches = [];

preg_match    ( $pattern, $subject, $matches, PREG_OFFSET_CAPTURE );
echo '<pre>';
print_r($matches);
echo '</pre>';

My pattern works for the following string

Hello "{{ @sql(SELECT TOP 1 name FROM table1 WHERE [id] = 5 ) }}" 

but when I need to use the pattern more than once in the text, it seems that my pattern search for the last occurrence of )}} instead of the next occurrence.

How can I update my pattern so it looks for one ore multiple matches?

Thank you

5
  • Possible duplicate of PHP preg_match and preg_match_all functions Commented Jun 13, 2016 at 17:45
  • 1
    Have you noticed that None of your sample strings like this "{{ @sql(SELECT TOP 1 name FROM table1 WHERE [id] = 5 }}" will match with a regex template like {{ @sql(WHATEVER QUERY GOES HERE) }} ? Commented Jun 13, 2016 at 17:48
  • Why are you using possessive quantifiers *+ ? Commented Jun 13, 2016 at 17:51
  • You have to use a regex tailored to parsing sql, otherwise you can't interpret what's between @sql(here) Commented Jun 13, 2016 at 17:56
  • @sln thanks for the correction. I just updated my question again to add the ) Commented Jun 13, 2016 at 18:21

3 Answers 3

1

After some discussion in the comments, I guess you need preg_replace():

<?php
$string = 'Hello, my name is "{{ @sql(SELECT TOP 1 name FROM table1 WHERE [id] = 5 ) }}" and my title is "{{ @sql(SELECT TOP 1 title FROM table1 WHERE [id] = 5 ) }}"';

$regex = '~
            \{{2}\h*@sql\(    # start of outer part
            (?P<query>[^()]+) # inner query
            \)\h*\}{2}        # end of outer part
        ~x';

$string = preg_replace($regex, '$1', $string);
echo $string;
# Hello, my name is "SELECT TOP 1 name FROM table1 WHERE [id] = 5 " and my title is "SELECT TOP 1 title FROM table1 WHERE [id] = 5 "

?>

See a demo on ideone.com.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for your help. Yes, I need the inner query. I am kinds confused on how to loop over the results. also, the inner query is giving me an additional ) at the end
Actually, all I am interested in is the inner query, I don't care about the rest. If it is easier just to get an array with only the inner queries that would be perfect
That makes more sense now. But the query is still returning an extra ) at the end.
Thank you Jan. This caused another issue in index 0 which is the exact string that is found. it is missing the ending ) }} so the query is being returned correctly but the string that is found it returnes {{ @sql(SELECT TOP 1 name FROM table1 WHERE [id] = 5 instead of {{ @sql(SELECT TOP 1 name FROM table1 WHERE [id] = 5 ) }} I need the whole thing so I can replace the whole string found with the result of the query
I want to replace the string starting at {{ @Sql(.....) }} with the result of the inner query. I got the query and executed it with no issue. but in order to replace {{ @Sql(.....) }} with the query result, I need to know the whole {{ @Sql(.....) }} if you look at the demo you posted you will see how the ending ) }} is removed but I need to keep it in order to replace the string correctly
|
0

You should just make the regex non-gready, by adding ?

...(.+?)...

(And also use preg_match_all)

1 Comment

Thank you for that. One thing I forgot to mention in my question "I will edit it next" is that the second index of the pattern is to extract query which is find inside the @sql(QUERY).
0

One way that I do it is this: You don't want any other braces within one pair of opening and closing braces. So you can specify this:

[^\{\}]+

The above pattern will match any string of characters that does not contain a curly bracket. Your complete pattern would be

/\{\{ ?@sql\([^\{\}]+\) ?\}\}/i

1 Comment

This return the entire text starting with {{ and ending with }}. All I need to return is the query that is between {{ @sql( and ) }}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.