Suppose
$string = " we will study integers & functions & matrices such as $$\begin{tabular}{ccc} a & b & c \\ a & b & c \\ \end{tabular}$$ ";
I would like to escape special latex characters (such as '&') outside math mode while leaving all the math stuff alone, so the desired output would be:
$string = " we will study integers \& functions \& matrices such as $$\begin{tabular}{ccc} a & b & c \\ a & b & c \\ \end{tabular}$$ ";
If anyone could lead me in a good direction I would be very grateful. thx
Something like this:
$text = ' we will study integers & functions & matrices such as $$\begin{tabular}{ccc} a & b & c \\ a & b & c \\ \end{tabular}$$ ';
$pattern = <<<'EOD'
~
[$&%#_{}^\\%]
(?:
(?<=\$)
(?:
\$ [^$]*+ (?:\$(?!\$)[^$]*)*+ \$\$ # display math mode (unofficial syntax)
|
[^$]+ \$ # ordinary math mode
) (*SKIP)(*F)
|
(?<=\\)
(?:
\[ [^\\]*+ (?>\\(?!])[^\\]*)*+ \\] # display math mode (square brackets)
|
\( [^\\]*+ (?>\\(?!\))[^\\]*)*+ \\ \) # ordinary math mode (parenthesis)
|
begin{(verbatim|math|displaymath|equation)} .*? \\end{\g{-1}}
|
verb\*?(.).*?\g{-1} | [\\@ ]
|
[a-z]+ (?:\[ [^]]* ] | {([^{}]*(?:{(?-1)}[^{}]*)*+)} | \( [^)]* \) | \s+ )* # latex keyword
)
(*SKIP)(*F)
|
(?<=%) \N* # comments
(*SKIP)(*F)
)?
~xs
EOD;
$text = preg_replace_callback($pattern, function ($m) {
return ($m[0] == '\\') ? '\\textbackslash{}' : '\\' . $m[0]; }, $text);
The pattern uses the backtracking control verbs combo (*SKIP)(*F)
. When the backtracking mechanism occurs and meets the (*SKIP)
token, the regex engine stops its backtracking walk and retry the whole pattern at the current position in the target string (at the (*SKIP)
position), so all character matched before the (*SKIP)
token are ignored and not retried. (*F)
(or (*FAIL)
) forces the pattern to fail that starts the backtracking mechanism.
Note that the string must be enclosed between single quotes if you don't want that PHP interprets all backslashes as escape sequences.