我正在尝试创建一个环境,它可以查找并替换其主体中的某些模式,并且不会与可能包含它的其他环境发生冲突。一种可能的使用场景可能如下所示:
\documentclass{article}
\usepackage{amsmath}
\begin{document}
\begin{gather}
\begin{foo}
a -> b \\ c -> \LaTeX
\end{foo}
\end{gather}
\end{document}
在这里,我的foo
环境应该用 替换->
(\to
在我的实际情况下,我有更多模式)。另一种可能的用法,这次没有gather
:
\documentclass{article}
\begin{document}
\begin{foo}
a -> \textbf{\TeX}
\end{foo}
\end{document}
你会怎么做?(我更喜欢使用\regex_replace_all
from expl3
,但这不是必需的。)
答案1
请参阅答案末尾的多个替换的一般情况
您是否正在寻找类似的东西?在这里,我使用一种listofitems
将要替换的文本用作输入的列表分隔符的方法。
\documentclass{article}
\usepackage{listofitems,amsmath}
\setsepchar{->}
\def\reptext{$\to$}
\newcommand\replace[1]{\readlist\pathlist{#1}%
\foreachitem\z\in\pathlist[]{\ifnum\zcnt=1\else\reptext\fi\z}}
\begin{document}
\replace{a -> b \\ c -> \LaTeX}
\end{document}
当然,要替换和替换的文本可以作为宏调用的一部分:
\documentclass{article}
\usepackage{listofitems,amsmath}
\newcommand\replace[3]{\setsepchar{#1}%
\readlist\pathlist{#3}%
\foreachitem\z\in\pathlist[]{\ifnum\zcnt=1\else#2\fi\z}}
\begin{document}
\replace{->}{$\to$}{a -> b \\ c -> \LaTeX}
\end{document}
...或者环境调用:
\documentclass{article}
\usepackage{listofitems,amsmath,environ}
\NewEnviron{replace}[2]{\setsepchar{#1}%
\readlist\pathlist{\BODY}%
\foreachitem\z\in\pathlist[]{\ifnum\zcnt=1\else#2\fi\z}}
\begin{document}
\begin{replace}{->}{$\to$}
a -> b \\ c -> \LaTeX
\end{replace}
\end{document}
具有多个替换的一般情况
\documentclass{article}
\usepackage{listofitems,amsmath,environ}
\newcommand\defxx[2]{\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter#1%
\expandafter\expandafter\expandafter{#2}}
\newtoks\septoks
\NewEnviron{replace}[2]{%
\setsepchar{,}%
\readlist*\pretext{#1}%
\readlist*\posttext{#2}%
\septoks{}%
\foreachitem\z\in\pretext[]{%
\ifnum\zcnt=1\else\global\septoks\expandafter{\the\septoks||}\fi%
\global\septoks\expandafter\expandafter\expandafter{%
\expandafter\the\expandafter\septoks\z}%
}%
\expandafter\setsepchar\expandafter{\the\septoks}%
\readlist\pathlist{\BODY}%
\foreachitem\z\in\pathlist[]{\ifnum\zcnt=1\else
\foreachitem\zz\in\pretext[]{%
\defxx\zzz{\pretext[\zzcnt]}%
\defxx\zzzz{\pathlistsep[\zcnt-1]}%
\ifx\zzz\zzzz\posttext[\zzcnt]\fi
}\fi\z%
}%
}
\begin{document}
\begin{replace}{ <-, ->, Z}
{$\leftarrow$,$\to$,\textbf{Hi Mom!}}
a -> b \\ c <- \LaTeX{} -> Z
\end{replace}
\end{document}
答案2
尽管 OP 在评论中表示基于 LuaLaTeX 的解决方案对于他们的用例来说“不是一个选择”,但其他人可能仍然会发现了解这样的解决方案是有益的。
解决方案包括(a)一个名为的 Lua 函数,foosub
它执行所需的字符串替换 - 请注意,完全可以设置多个字符串替换 - 和(b)一个名为的 LaTeX 环境,foo
它执行以下指令:
输入后,将
foosub
函数分配给 LuaTeX 的process_input_buffer
回调,使其像输入流上的预处理器一样运行。这样,例如,<->
被替换为\leftrightarrow
前TeX 开始执行其通常的处理步骤。退出时,
foosub
从process_input_buffer
回调中删除。
我所知道的关于此代码适用性的唯一限制(除了在 LuaLaTeX 下编译文档的能力之外)是环境foo
必须包含gather
环境,而不是相反。
\documentclass{article}
\usepackage{amsmath,amssymb}
\usepackage{unicode-math} % <-- Important, to avoid interactions
% with code in 'umsa.fd' file.
\usepackage{luacode} % for "luacode" environment
%% Lua-side code: Lua function to perform the string substitutions
\begin{luacode}
function foosub ( s )
s = s:gsub ( "<%->" , "\\leftrightarrow " )
s = s:gsub ( "%->" , "\\rightarrow " )
s = s:gsub ( "<%-" , "\\leftarrow " )
return ( s )
end
\end{luacode}
%% LaTeX-side code: LaTeX environment called "foo"
\newenvironment{foo}%
{\directlua{luatexbase.add_to_callback (
"process_input_buffer", foosub , "foosub" )}}%
{\directlua{luatexbase.remove_from_callback (
"process_input_buffer", "foosub" )}}
\begin{document}
\begin{foo}
\begin{gather}
a -> b \\
c <- d \\
e <-> \text{\LaTeX}
\end{gather}
\end{foo}
\end{document}