Jump to content

[SOLVED] continue from other post...Pattern Match


glenelkins

Recommended Posts

Please refer to my other post: http://www.phpfreaks.com/forums/index.php/topic,254076.0.html

 

another quick question... now i have the content from the middle and i have it replacing with preg_replace  how can i actually return everything thats between {cms params here} because i dont actually want to replace the {cms PARAMS}...{/cms} bits just whats between them

Link to comment
Share on other sites

sorry to put a downer MrAdam  but iv just modified the expression to this:

 

    $pattern = '/\{cms[^\}]*name="' . $region_id . '"[^\}]*\}([^\{]+)\{\/cms\}/'; 

 

and its matching everything to do with the {cms} tag its not matching it where the name="$region_id"  so its not correct! I dont want it to pick out every tag on the page, just the one with the correclt supplied region_id

 

Link to comment
Share on other sites

this is what i wanted:

 

$pattern = '%({cms)([^\}]*)(name="' . $region_id . '")([^\}]*)(})(.*)({/cms})%';

 

Are all those captures necessary? Note that ({cms) will be stored into $1, ([^\}]*) into $2, (name="' . $region_id . '") into $3, etc.. Seems like those captures can be simplified..

 

Also note that the use of .* is generally frowned upon (for speed / accuracy reasons). It is dependant on the situation of course... if there is more stuff after what the pattern matches in the string, you run into speed issues...if there is more similar stuff in the string that the pattern can match, you run into speed and accuracy issues. To have a better understanding, you can have a look at this thread (post #11 and 14). So depending on what the string looks like, it might be advisable to make .* lazy - (.*?)

 

Also, you don't have to escape the } characters in your character class. So [^\}]* could become [^}]*

 

Example:

$region_id = 'NAME_HERE'; // I use this otherwise I have no $region_id variable to test with
$replace = ' NOTHING HERE ';
$str = '{cms HERE CAN HAVE ANYTHING IN ANY ORDER BUT MUST HAVE name="NAME_HERE"} ANYTHING HERE {/cms}';
$str = preg_replace('#({cms[^}]+name="' . $region_id . '"[^}]*}).+?({/cms})#', '$1'.$replace.'$2', $str);
echo $str;

 

If the ANYTHING HERE bit in the string is spread across multiple lines, simply add the s modifier after the closing delimiter (so that (.+?) can include newlines).

Link to comment
Share on other sites

hi furthere to my earlier discussion. i have this almost working. here is my pattern:

 

$region_id = "test_region_name";
$pattern = '%{cms[^}]*name="' . $region_id . '"[^}]*}(.*){/cms}%';

 

This will match a string like the following without an issue.

 

{cms name="test_region_name" type="text"}Content Here{/cms}

 

But when it comes to something like this:

 

{cms name="test_region_name" type="text"}<p>Content Here</p>{/cms}

 

It doesnt find a match

 

(Appologies for the (.*) i have only just read your comments on that )

Link to comment
Share on other sites

I'm confused by your pattern however.. You are using a single capture on anything in between{cms.....} and {/cms}

Going by your initial post, you want to replace what is in between those with something else.. how are you going to do this with the current capture setup (unless there is some miscommunication)?

 

The way I saw it, capture anything but that section, and simply reconstruct the cms tag by inserting the first captured part, the replacement , then the second captured part. No?

Link to comment
Share on other sites

ok the idea is we have a string something like one of these:

 

<body>

    {cms name="test_name_1" type="text"}CONTENT STUFF HERE{/cms}

    {cms type="text" name="test_name_2" style="width: 100%;"}CONTENT STUFF HERE{/cms}

</body>

 

Now when a function is called say test() it sends over the "name" parameter:

 

function test ( $name, $replace_content ) {

}

test ( "test_name_1", "REPLACE WITH THIS" );

 

now the pattern in this example function would be

 

$pattern = '%{cms[^}]*name="' . $name . '"[^}]*}(.*){/cms}%';

 

So what its doing is looking in the html code abover for a tag that starts with {cms and within the first tag looks for the name="test_name_1"  when its found that tag it will replace what is between the opening {cms name="test_name_1"} and {/cms}

 

Following?

 

The pattern should allow the name paremeter to fall anywhere in the opening tag so the parameters can be {cms type="text" name="name_here"}{/cms} {cms name="name_here" type="text"}{/cms} or any combination you like

 

Now the pattern i have works fine at replacing the content bit with text, but if the content part contains HTML tags like <p>, <div> etc the pattern doesnt match so this one works fine:

 

{cms name="test"}TEXT HERE{/cms}

 

But this doesnt

 

{cms name="test"}<p>TEXT HERE</p>{/cms}

Link to comment
Share on other sites

hmm

 

iv just changed the pattern to this:

 

$pattern = '%{cms[^}]*name="' . $name . '"[^}]*}([^}]*){/cms}%';

 

And now it seems to work

 

I thought (.*) means any character 0 or more times so why does the old one not work: $pattern = '%{cms[^}]*name="' . $name . '"[^}]*}(.*){/cms}%';

Link to comment
Share on other sites

Yes, I follow what you are saying.

The dot is a wildcard so to speak that matches anything that is not a newline (\n) by default. The star is a zero or more times quantifier (but the key I was trying to explain in the link I last posted) is that this is a greedy quantifier. So by using .* instead of .*?, you run the risk of the pattern matching more than you want it to. My previous pattern seems to work fine:

 

example:

$str = <<<HTM
<body>
{cms name="test_name_1" type="text"}<p>CONTENT STUFF HERE</p>{/cms}
{cms type="text" name="test_name_2" style="width: 100%;"}<div>CONTENT STUFF HERE</div>{/cms}
</body>
HTM;

function replace ($name, $replace_content, $string) {
$string = preg_replace('#({cms[^}]+name="' . $name . '"[^}]*}).+?({/cms})#', '$1'.$replace_content.'$2', $string);
}

replace('test_name_1', 'REPLACE WITH THIS', &$str);
echo $str;

 

Output:

{cms name="test_name_1" type="text"}REPLACE WITH THIS{/cms} {cms type="text" name="test_name_2" style="width: 100%;"}
CONTENT STUFF HERE
{/cms}

Link to comment
Share on other sites

ok this is getting frustrating!

 

The pattern matches and replaces text in this line for example:

 

<h1>{cms type="text" name="testing1"}Testing Text Here{/cms}</h1>

 

but it wont find a match for something like this:

 

{cms type="text" name="testing2"}
<p>Paragraph test 1</p>
<p>Paragraph test 2</p>
{/cms}

Link to comment
Share on other sites

right now im real annoyed! I just tried it again but i put both the <p></p> areas on one line and it worked fine. Why isnt it working if the paragraph tags are on 2 lines or more?

Link to comment
Share on other sites

Daniel0  could you give me a quick example of a multi-line modifier working

 

Clearly i should use the "m" modifier but i dont know how you use that in preg_replace or preg_match ??

Link to comment
Share on other sites

well in my expression is this correct??

 

%({cms[^}]*name="' . $region_id . '"[^}]*}).+?m({/cms})%

 

i have put the "m" modifier there

 

Well that doesnt work!! I also tried this

 

%({cms[^}]*name="' . $region_id . '"[^}]*}).+?ms({/cms})%

 

with the "m" and "s" modifiers...still not working!

Link to comment
Share on other sites

Would save yourself a lot of time if you actually read people's responses.

 

I agree. glenelkins, I mentioned in post#5 that if the content spans across multiple lines, add the s modifier:

 

If the ANYTHING HERE bit in the string is spread across multiple lines, simply add the s modifier after the closing delimiter (so that (.+?) can include newlines).

 

So for example, if you had multiple lines in the text_name_1 cms;

$str = <<<HTM
<body>
{cms name="test_name_1" type="text"}
<p>CONTENT STUFF HERE</p>
<p>CONTENT STUFF HERE</p>
{/cms}
{cms type="text" name="test_name_2" style="width: 100%;"}<div>CONTENT STUFF HERE</div>{/cms}
</body>
HTM;

function replace ($name, $replace_content, $string) {
$string = preg_replace('#({cms[^}]+name="' . $name . '"[^}]*}).+?({/cms})#s', '$1'.$replace_content.'$2', $string);
}

replace('test_name_1', 'REPLACE WITH THIS', &$str);
echo $str;

 

 

 

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.