If you just want to convert '&' in content and avoid tags (ie: attribute values)
and avoid script blocks, something like below will work for most occurances.
However, it should be noted that attribute values should be converted as well.
And doing that requires a lot more work.

Working sample http://www.ideone.com/9MhCq

<?php

$html=<<<EOD
 <some &ta&g> S&P &&more; and &some; <more> &notme;
  && &#209; &#xa92F;
 <script flavor?>
   val && this & this 
 </script>
 &
EOD;

$rxent = '(?:&(?:[A-Za-z_:][\w:.-]*|\#(?:[0-9]+|x[0-9a-fA-F]+));)';

$rxtag =
'<
 (?:
     \?php\s+.*?\?
  |  (?:
       (?:
           (?:script|style)\s*
         | (?:script|style)\s+(?:".*?"|\'.*?\'|[^>]*?)+\s*
       )> .*? </(?:script|style)\s*
     )
  |  (?:
         /?[A-Za-z_:][\w:.-]*\s*/?
       |  [A-Za-z_:][\w:.-]*\s+(?:".*?"|\'.*?\'|[^>]*?)+\s*/?
       | !(?:DOCTYPE.*?|--.*?--)
     )
 )
 >
';

$rxmain = "~(?xs:((?:$rxtag)+) | ((?!$rxent)&))~";


print "$html\n\n";

$html = preg_replace_callback($rxmain, 'fixamp_cb', $html);

print "$html\n";

function fixamp_cb( $matches ) {
    # Return tags and script blocks unchanged.
    if (isset($matches[1]) && $matches[1])
       return $matches[1];
    return '&amp;';
}

?>
Answer from user557597 on Stack Overflow
Top answer
1 of 2
1

If you just want to convert '&' in content and avoid tags (ie: attribute values)
and avoid script blocks, something like below will work for most occurances.
However, it should be noted that attribute values should be converted as well.
And doing that requires a lot more work.

Working sample http://www.ideone.com/9MhCq

<?php

$html=<<<EOD
 <some &ta&g> S&P &&more; and &some; <more> &notme;
  && &#209; &#xa92F;
 <script flavor?>
   val && this & this 
 </script>
 &
EOD;

$rxent = '(?:&(?:[A-Za-z_:][\w:.-]*|\#(?:[0-9]+|x[0-9a-fA-F]+));)';

$rxtag =
'<
 (?:
     \?php\s+.*?\?
  |  (?:
       (?:
           (?:script|style)\s*
         | (?:script|style)\s+(?:".*?"|\'.*?\'|[^>]*?)+\s*
       )> .*? </(?:script|style)\s*
     )
  |  (?:
         /?[A-Za-z_:][\w:.-]*\s*/?
       |  [A-Za-z_:][\w:.-]*\s+(?:".*?"|\'.*?\'|[^>]*?)+\s*/?
       | !(?:DOCTYPE.*?|--.*?--)
     )
 )
 >
';

$rxmain = "~(?xs:((?:$rxtag)+) | ((?!$rxent)&))~";


print "$html\n\n";

$html = preg_replace_callback($rxmain, 'fixamp_cb', $html);

print "$html\n";

function fixamp_cb( $matches ) {
    # Return tags and script blocks unchanged.
    if (isset($matches[1]) && $matches[1])
       return $matches[1];
    return '&amp;';
}

?>
2 of 2
0

Why not something simple like:

$html = preg_replace('/([^&])&([^&])/', '$1&amp;$2', $html);

If you want to avoid replacing all ampersands inside Javascript, add lookahead/behind for script tags, or first split the document on script tags, and only run the replace on the non-script parts.

$html = preg_split('/<\/?script>/', $html);
foreach ($html as v) {
  if ($piece[0] == "<") {
    $html[$k] = preg_replace('/([^&])&([^&])/', '$1&amp;$2', $v);
  } else {
    $html[$k] = "<script>" . $html[$k] . "</script>";
}

This will need some modification if your script tags have attributes.

If you're sanitizing user content, then you might be better using the tools that are already available. See HTML Purifier

🌐
Infoheap
infoheap.com › home › tutorials › php › php regex
Php look ahead and look behind regex examples - InfoHeap
January 4, 2016 - <?php $str = "something world"; ... ?> ... The flag i after / is used for ignoring case. The lookahead or lookbehind does not become part of pattern match ($matches in preg_match) or replaced content (in preg_replace)....
Discussions

PHP negative lookahead regex not working - Stack Overflow
Anyway, I'd recommend preg_quoteing ... . preg_quote($search, "/") . "(?!=)/i", $replacement, $string, -1, $count); ... Actually you need to escape $ character by a backslash \ in your pattern. Also to make it more confident, you can add \s* which means zero or more white space(s) before = character. ... (?! negative Lookahead which checks ... More on stackoverflow.com
🌐 stackoverflow.com
June 16, 2016
preg match - PCRE regex lookahead - Stack Overflow
I can't get PCRE lookahead to work correctly, help will be appreciated, I am finding it difficult to explain but here we go, take this pattern for example: /^\/page(\/?[a-z0-9\.\_\-]+)*\/?$/i This More on stackoverflow.com
🌐 stackoverflow.com
PHP regex lookahead not working as expected - Stack Overflow
The lookahead for the period does not seem to work as expected. ... Save this answer. ... Show activity on this post. If you're looking to compare the version, you can strip on the space and then use version_compare(). If you just want the numeric representation, use a regex to simply use preg_replace... More on stackoverflow.com
🌐 stackoverflow.com
php - Negative Look-back in preg_replace() with numbered Backreferences, has no effect - Stack Overflow
A way is to use ()|urlpattern with preg_replace_callback. When the group1 is defined you return it, when it is not defined you return the whole match embedded between "a" tags. 2014-07-02T07:39:00.613Z+00:00 ... Note too that in (?! More on stackoverflow.com
🌐 stackoverflow.com
June 5, 2017
🌐
Webmaster World
webmasterworld.com › forum88 › 1480.htm
Lookbehind & Lookahead [Information] - PHP Server Side Scripting forum at WebmasterWorld - WebmasterWorld
Lookahead takes the form (?=X) Lookbehind takes the form (?<=X) ... $text="The big hairy dog loves eating minced meat. The interesting parrot hates eating minced meat."; Suppose we want to change minced meat for chocolate, but only where the ...
🌐
PHPBuilder
board.phpbuilder.com › d › 10355941-help-with-a-preg-replace-lookahead
Help With a Preg_Replace Lookahead - PHPBuilder Forums
June 12, 2008 - Hi, I have a preg_replace that finds images tags: /<img src="(.)"(.)\/>/isUe It works great but I would like to only match if the image tag is NOT in...
🌐
PHP Tutorial
phptutorial.net › home › php tutorial › regex lookahead
Regex Lookahead - PHP Tutorial
April 7, 2025 - The lookahead means to search for A but matches only if followed by B. For a number followed by the string lb, you can use the following pattern: ... <?php $pattern = '/\d+(?=lb)/'; $str = '2 chicken weigh 30lb'; if (preg_match($pattern, $str, $matches)) { print_r($matches); // 30 }Code language: ...
🌐
PHP
php.net › manual › en › regexp.reference.assertions.php
PHP: Assertions - Manual
Lookahead assertions start with (?= for positive assertions and (?! for negative assertions. For example, \w+(?=;) matches a word followed by a semicolon, but does not include the semicolon in the match, and foo(?!bar) matches any occurrence ...
🌐
Stack Overflow
stackoverrun.com › de › q › 2017156
Loading...
We cannot provide a description for this page right now
Find elsewhere
🌐
Medium
wearedopethemes.medium.com › replacing-ereg-replace-with-preg-replace-in-php-for-regex-handling-e4cdf53450e2
Replacing ereg_replace() with preg_replace() in PHP for Regex Handling | by DopeThemes.com | Medium
September 3, 2024 - In this example, preg_replace() uses a positive lookahead (?=\s+pie) to match the word “apple” only when it is followed by “pie”. The result is that only “apple” in “apple pie” is replaced with “orange”.
🌐
Regular-Expressions.info
regular-expressions.info › lookaround.html
Regex Tutorial: Lookahead and Lookbehind Zero-Length Assertions
You can use any regular expression inside the lookahead (but not lookbehind, as explained below). Any valid regular expression can be used inside the lookahead. If it contains capturing groups then those groups capture as normal and backreferences to them work normally, even outside the lookahead.
🌐
RegExr
regexr.com › 3ehvj
negative lookahead PHP
RegExr is an online tool to learn, build, & test Regular Expressions (RegEx / RegExp).
🌐
Blogger
sabirul-mostofa.blogspot.com › 2011 › 05 › php-regex-lookaround-assertion.html
SIMPLE_THOUGHTS: PHP regex lookaround assertion: lookbehind and lookahead
May 28, 2011 - $text = 'demo.mp3, shakira.mp4,lorum ipsum'; if(preg_match_all('/\.mp3|\.mp4/', $text,$matches)): foreach($matches as $key => $match){ $matches[$key] = str_replace('.', '' ,$matches[$key]); } endif; var_dump($matches); But this is ugly, we can use the lookbehind assertion to make the code simple: preg_match_all('/(?<=.)mp3|mp4/', $text,$matches); var_dump($matches); Let's Go Back: Check The Basic: What are the lookahead and lookbehind assertions?
🌐
Reddit
reddit.com › r/phphelp › preg_replace: find the right match, but don't replace certain characters
r/PHPhelp on Reddit: Preg_Replace: Find the right match, but don't replace certain characters
October 12, 2022 -

I have arrays (I condensed it for reddit) that are used to find & replace certain words that a user inputs in a text area.

$PATTERNS = array('/\Wdc\W/i', '/\Wtr\W/i') $RESULTS = array('ab', 'ef')

For the first entry in the $PATTERNS array, I'd like to search what the user inputs and replace text like '6dc', '12dc', '.dc', 'dc', ':dc', etc. However, I need the numbers and punctuation to stay when the dc portion is being replaced by 'ab'. I added the boundaries at the front and end as I don't want to make any changes if there are letters at the front and end, so words like 'padc' and 'dcom' would stay the same.

Example input -> output goal:

6dc -> 6ab

dc5 -> ab5

.dc -> .ab

dc. -> ab.

pdc -> pdc (no change)

*dc -> *ab

dc* -> ab*

Incorrect output I'm getting from my current code:

6dc -> ab

dc5 -> ab

.dc -> ab

dc. -> ab

What I've tried:

I've looked at incorporating in a lookbehind/lookahead and (*SKIP) (*FAIL), but I can't seem to figure it out.