test
test

Reputation: 3

PHP Regex ignore string between specific characters

I use regex to add markup to my website and I would like for **string** to only make the string bold if the string and asterisks are not between four brackets like so: [[**string**]] in this case the four asterisks and the string should stay the same and not dissapear or turn bold. I hope this is possible with regex.

For detecting when a string is between four asterisks I use this regex /**(.+?)**/ And for detecting when a string is between fourd brackets I use /[[(.+?)]]/s

Upvotes: 0

Views: 108

Answers (3)

Mohammed Elhag
Mohammed Elhag

Reputation: 4302

What you need id to match only **string** not preceded by [ and should so :

  • (?<!\[) Negative lookbehinds to make sure tring not preceded by [
  • (?:[\*]{2}) string must be precded by two **
  • ([^\[\]\*]+) string match
  • (?:[\*]{2}) string must end with two **

(?<!\[)(?:[\*]{2})([^\[\]\*]+)(?:[\*]{2})

Demo

PHP code :

<?php
$str="[[**string**]]**string**[[**string**]]**string****string****string** [[**string**]]**string**[[**string**]]**string****string****string**[[**string**]]**string**[[**string**]]**string**[[**string**]][[**string**]]**string****string****string****string**abcd*abcdefg*abcdefgh**abcd***[**string**]]";
$pattern = '/(?<!\[)(?:[\*]{2})([^\[\]\*]+)(?:[\*]{2})/';
$replacement = '<b>$1</b>';
$str= preg_replace($pattern, $replacement,$str);
print $str;
?>

Upvotes: 0

mickmackusa
mickmackusa

Reputation: 48041

Without seeing how much variability there is in your input string, I'd say you can simply match and discard the substrings that are double square brace and double asterisk wrapped and then match&capture the non brace wrapped substrings that are only asterisk wrapped.

There are fringe cases (like nested square braced substrings) where this will fail, but I don't know if they are reasonably likely to occur.

Code: (Demo)

$text = <<<TEXT
Text **bold** [[**not
bold**]]
TEXT;

echo preg_replace(
         '~\[{2}\*{2}.*?\*{2}]{2}(*SKIP)(*FAIL)|\*{2}(.*?)\*{2}~s',
         '<b>$1</b>',
         $text
     );

Output:

Text <b>bold</b> [[**not
bold**]]

Upvotes: 0

The fourth bird
The fourth bird

Reputation: 163577

You might use

(?<!\[\[|\*)\*\*(?!\*)(.+?)(?<!\*)\*\*(?!\*|]])

The pattern matches

  • (?<!\[\[|\*) Negative lookbehind, assert [[ or * to the left
  • \*\*(?!\*) Match ** and negative lokoahead to assert not * to the right
  • (.+?) Capture group 1, match 1+ chars as least as possible
  • (?<!\*)\*\* Negative lookbehind, assert not * to the left and match **
  • (?!\*|]]) Negative lookahead, assert not * or ]] to the right

Regex demo | Php demo

Another option might be matching all that you don't want and then making use of SKIP FAIL

(?:\[\[.*?]]|\*{3,}.*?\*+|\*+.*?\*{3,})(*SKIP)(*F)|\*\*(.+?)\*\*

Regex demo | Php demo

Upvotes: 1

Related Questions