Substring regex

Is there a way , within ONE PHP regex statement , to evaluate only part of a regex selected string? Hmm… that doesnt seem to explain what I mean very well. Lets, for example, say you had a string of text, SOME of it contained something SIMILAR to HTML tags… "
<ol>
" and "
</ol>
“, so you wanted to preg_replace for "
\*” BUT only in the text contained between ANY occurrence of "
<ol>
" and "
</ol>
".

So far the only way I see of accomplishing this to use preg_match, a remembering array, run the sub-regex on the captured result from the preg_match, then another loop str_replacing items in the remembering array with the regexed captured result from the preg_match. Which is rather convoluted, even just to describe.

Any suggestions would be greatly appreciated.

Hi dresden_phoenix

Is this what your looking for:


$text = "\
<ol>\
 <li>This is the text between the ol. </li> \
</ol>\
";

/*
* Regex searches on the new lines and the ols, 
* then it uses a group match to get the text inbetween.
*/$match = preg_match("/\\\
<ol>\\\
(.*)\\\
<\\/ol>\\\
/", $text , $matches);
print_r($matches);

/* Outputs */
Array ( 
[0] => This is the text between the ol.  
[1] => <li>This is the text between the ol.</li>

Regards,
Steve

I think the simple answer is ‘no, it will require 2 statements.’

Wow, I have to stop answering Dresden’s posts, no fault of his own but I seem to misinterpret his needs way too often. I re-read what you asked have been trying a number of things but @StarLion; has seemed to tell you correctly.

I promise I will steer clear of your questions in the future and sorry for the wasted post.

Regards,
Steve

:frowning: That suck, as normally you actually end up answering my Q’s correctly, Storm.

@ star…

Does that mean looping statements? I mean if the original string contained multiple OLs

Thanks… I guess I’ll keep trying and glad that I have not put you off :slight_smile:

Could you give a full example in an code block an specific example, is it:


  • <ol>
    <li>some text
    and more text</li>
    </ol>
    ’ : so you would want
    <ol>
    <li>some text</li>
    </ol>
    or

  • <ol>

    <li>some text</li>
    </ol>
    ’ : so it would become
    <ol>

    </ol>
    or
  • something else?

I have been fiddling and found something that can give you
<ol>
<li></li>
</ol>
but I am not sure if this is helpful because if you are trying to preserve some text inside the <ol> and/or the <li> then I wanted to try something else.

Regards,
Steve

If I understand your question right, you have to use lookahead and lookbehind.

OK… so lets say you have a block of text, you want to change any AND ALL \

  • that happens to be within <OL>/</OL> to <LI> ( just to keep this task ‘simple’) But what you dont whant to change is any \
  • that are OUTSIDE the <OL>/</OL>:

"
<ol>
*Change us!
*list item
*list item
</ol>
lorem ipsum … blah bla blah

*dont change me
*dont change me

more lorem ipsum

<ol>
*Change us also !
*list item
</ol>
lorem ipsu"

I am probably not doing this right, but the problem with look ahead/behind in this case is that then it only changes ONE of the \

  • between the tags not all. What am searching for is a way to change all occurrences of a pattern within ONLY WITHIN all occurrences of another pattern.
preg_match_all("<ol>.*?</ol>",$input,$blocks); //Find all OL's.
$store = $blocks; //Create a duplicate for later use.
$blocks = preg_replace("\
","<li>",$blocks); //Change the blocks.
$input = preg_replace($store,$blocks,$input); //Insert the replacements

Note: This -will- fark up if you nest OL’s.

I want to say this would be easier with a recursive DOM parser…

Darn you @StarLion; ! I have been trying to figure out the best way to do this and your solution is quite eligante!

Thanks,
Steve

Sorry guys I had to put this on hold for while,

Star
I tired your suggestion, but i got the following sintax error

Warning: preg_replace(): Delimiter must not be alphanumeric or backslash in - on line 41 ( the last line of your code), I also had to add delimiters to the other preg_match and first preg_replace but i figured you left that for me to do. It appears the problem arises because the regex pattern stored in the array doesnt have a delimiter?

I tried the following alteration:


preg_match_all("#<ol>.*?</ol>#",$input,$blocks); //Find all OL's.
$store = $blocks; //Create a duplicate for later use.
foreach ($store as $k=>$v){$store[$k]="#$v#";}
$blocks = preg_replace("#\
#","<li>",$blocks); //Change the blocks.
$input = preg_replace(  $store ,$blocks,$input); //Insert the replacements  echo $input;
echo $input;


but it only changed the first
*…:confused:

any suggestions. Either way thanks for your input on this.

foreach ($store as $k=>$v){$store[$k]=“#$v#”;}

Why is that there?

EDIT: NM, silly me. need pattern delimiters.

So i got a bit more refined. Go me.


echo preg_replace_callback("%<ol>.*?</ol>%s",create_function('$matches','return preg_replace("%\
%s","<li>",str_replace("\
</ol>","</ol>",$matches[0]));'),$input);

Yes “Go you! @StarLion;”! Nice work using the callback and nice example of use in this context!

BRILLIANT, STAR!!!

Nice work using the callback and nice example of use in this context!
ditto and thanks so much