Reputation: 3
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
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})
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
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
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 rightAnother option might be matching all that you don't want and then making use of SKIP FAIL
(?:\[\[.*?]]|\*{3,}.*?\*+|\*+.*?\*{3,})(*SKIP)(*F)|\*\*(.+?)\*\*
Upvotes: 1