Why doesn't my preg_replace wildcard work?

Discussion in 'PHP' started by mark_s, Apr 8, 2009.

  1. #1
    I'm trying to trigger all words with brackets around it. So in the below example, "(test)" should be replaced with "test".

    <? $test = '(test)';
    $test = preg_replace('("[^"]*")', 'test', $test);
    echo $test; ?>
     
    mark_s, Apr 8, 2009 IP
  2. joebert

    joebert Well-Known Member

    Messages:
    2,150
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #2
    Those are "parenthesis", these are brackets, "[ ]".

    In any event parenthesis, brackets, and braces all have special meaning in a regular expression you can use with the preg_* functions so you will have to escape them using a backslash " \ " if you want them to be interpreted literally.

    Try this.
    $str = preg_replace('#\(([a-z\s]+)\)#i', '$1', $str);
    Code (markup):
     
    joebert, Apr 8, 2009 IP
  3. mark_s

    mark_s Peon

    Messages:
    497
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    0
    #3
    Thank you very much!
     
    mark_s, Apr 8, 2009 IP
  4. mark_s

    mark_s Peon

    Messages:
    497
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    0
    #4
    There's a slight problem... I put some text next to your code so "Read more (1404 words)" is removed but it breaks the code.

    <?  $test = 'The story article, Read more (1404 words)';
    $test = preg_replace('Read more #\(([a-z0-9\s]+)\)#i', '', $test);
    echo $test; ?>
    Code (markup):
     
    mark_s, Apr 9, 2009 IP
  5. joebert

    joebert Well-Known Member

    Messages:
    2,150
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #5
    The hashes/pound-symbols ( # ) are pattern delimiters, they mark the beginning and end of the pattern. Make sure your pattern is inside of the pattern delimiters.
     
    joebert, Apr 9, 2009 IP
  6. mark_s

    mark_s Peon

    Messages:
    497
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    0
    #6
    Thanks joebert!

    I have two final questions, sorry if I'm annoying anyone.

    1) How do I make this wildcard only apply to the line it is on rather than have it remove everything on the entire page before 'test'.
    preg_replace('#(.*?)test#', '', $test);
    Code (markup):
    2) This should only remove the line of text that contained "(1 audio)" in it, instead it removes half the page because it deletes all the content to a <strong> tag further up the page even though it doesn't mention "(1 audio)".
    $test = preg_replace('#<strong>(.*?)\(1 audio\):</strong>#i', '', $test);
    Code (markup):
     
    mark_s, Apr 9, 2009 IP
  7. joebert

    joebert Well-Known Member

    Messages:
    2,150
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #7
    1) Switch it from an "anything zero or more times" pattern, to an "anything other than a linebreak one or more times" mattern.

    Also, I tend to stay away from using the questionmark to turn off greediness within a pattern because it can get confusing with long patterns where the pattern flags aren't always visible while you're editing it.
    Instead, I use the "U" flag and reserve the greediness inverter (?) to turn it back on when needed.

    I'm actually not sure off the top of my head whether greediness even applies in this situation.

    #([^\r\n]+)test#U
    Code (markup):
    2) You may be able to apply the same "anything other than linebraks" logic from #1.
     
    joebert, Apr 10, 2009 IP
    mark_s likes this.
  8. mark_s

    mark_s Peon

    Messages:
    497
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    0
    #8
    Neither of those worked or did I implement your suggestions wrong?

    1 - It worked but removed all the content above where the video was showing:

    $article['body'] = preg_replace('#([^\r\n]+)\(1 video\)#U', 'Multimedia', $article['body']);
    Code (markup):
    2 - Worked but removed all the content above until it found <strong> tags even though that tag was not next to "(1 video)".

    $article['body'] = preg_replace('#<strong>([^\r\n]+)\(1 video\)#U', '<strong>Multimedia', $article['body']);
    Code (markup):
     
    mark_s, Apr 10, 2009 IP
  9. joebert

    joebert Well-Known Member

    Messages:
    2,150
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #9
    Post an example of the content before processing, and what it should look like after procesing.
     
    joebert, Apr 11, 2009 IP
  10. mark_s

    mark_s Peon

    Messages:
    497
    Likes Received:
    10
    Best Answers:
    0
    Trophy Points:
    0
    #10
    I've been doing some testing but still end up with the same issue with both your wildcard methods. Your code seems to change things on the page that is above the line the pattern is intended to look at.

    Example

    Intent: Change every line that mentions '(1 video)' to say 'Multimedia' instead.

    Problem: It does do that but also removes the match statistics header text and image.
    Code:
    <? $test = 'The way I played at the end will give me a great indication of how I need to play.</q><br /><br /><div class="more_intro">Match statistics:</div><img src="http://www.murraysworld.com/forum/index.php?action=dlattach;topic=13728.0;attach=5145;image" alt="" align="absbottom" border="0"><br /><br /><div class="more_intro">Match highlights (1 video):</div><div class="more_content">VIDEO HERE</div><br /><br /><div class="more_intro">Murray predicts successful clay-court season (1 video):</div><div class="more_content"><br />
    VIDEO HERE</div>';
    
    $test = preg_replace('#<div class=\"more_intro\">(.*?)\(1 video\):</div>#i', 'Multimedia:', $test);
    
    echo $test; ?>
    Code (markup):
     
    mark_s, Apr 18, 2009 IP
  11. joebert

    joebert Well-Known Member

    Messages:
    2,150
    Likes Received:
    88
    Best Answers:
    0
    Trophy Points:
    145
    #11
    What about this ?

    It assumes there's no HTML inside the "more_intro" elements, since the example you posted doesn't have any.

    <?php
    
    $test = 'The way I played at the end will give me a great indication of how I need to play.</q><br /><br /><div class="more_intro">Match statistics:</div><img src="" alt="" align="absbottom" border="0"><br /><br /><div class="more_intro">Match highlights (1 video):</div><div class="more_content">VIDEO HERE</div><br /><br /><div class="more_intro">Murray predicts successful clay-court season (1 video):</div><div class="more_content"><br />
    VIDEO HERE</div>';
    
    $test = preg_replace(
    	'#<div class="more_intro">[^<]*\(\d+ videos?\):</div>#i',
    	'<div class="more_intro">Multimedia:</div>',
    	$test
    );
    
    echo $test;
    
    ?>
    Code (markup):
     
    joebert, Apr 18, 2009 IP