PHP's htmlentities()
has double_encode
argument for this.
If you want to do things like that in regular expressions, then negative assertions come useful:
preg_replace('/&(?!(?:[[:alpha:]][[:alnum:]]*|#(?:[[:digit:]]+|[Xx][[:xdigit:]]+));)/', '&', $txt);
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…