答案1
这是一个基于 LuaLaTeX 的解决方案。如果你被迫使用 pdfLaTeX,那么你可能就倒霉了。不过,希望这个答案对其他读者仍然有用。
中缀分数表示法(例如a/b
和1/2
)的一个主要问题是,当 TeX 有机会注意到/
输入流中存在符号时,原本应该构成分子的材料已经消失了;通过退格来恢复分子将非常繁琐(甚至是不可能的)。基于预处理器的方法似乎更有希望。幸运的是,LuaTeX 提供了回调process_input_buffer
,它非常适合预处理。
以下示例代码提供了一个执行中缀到 dfrac 转换的 Lua 函数。唯一的语法要求是分子和分母中的字符只能由字母和阿拉伯数字组成。(不允许使用括号)/
允许在(斜杠)符号的左侧或右侧使用空格。
鉴于替换/
为\dfrac
,此 Lua 函数应该绝不不能在内联数学模式材料上运行,更不用说文本模式材料了,否则它会对任何/
字符造成严重破坏。因此,代码还提供了两个 LaTeX 宏 --\ReplaceOn
和\ReplaceOff
--,它们激活和停用 Lua 函数。我建议您\ReplaceOn
在包含中缀分数的每组方程式的开头插入一条指令,并\ReplaceOff
在每个这样的组的结尾插入一条指令。
% !TEX TS-program = lualatex
\documentclass{article}
%% Lua-side code
\usepackage{luacode}
\begin{luacode*}
function sltodf ( s ) -- "slash to dfrac"
return ( string.gsub ( s , "(%w+)%s-/%s-(%w+)" , "\\dfrac{%1}{%2}" ) )
end
\end{luacode*}
%% TeX-side code
\newcommand\ReplaceOn{\directlua{luatexbase.add_to_callback (
"process_input_buffer", sltodf, "sltodf" )}}
\newcommand\ReplaceOff{\directlua{luatexbase.remove_from_callback (
"process_input_buffer", "sltodf" )}}
\usepackage{amsmath} % for '\dfrac' macro
\begin{document}
\ReplaceOn
\[ m /n + pq / rs = 1 / 2 - 21/ 32 . \] % lots of whitespace
\[m/n+pq/rs=1/2-21/32.\] % no whitespace at all
\[ 2a /3b + pq/rs = a / 5 - 61c/41d . \] % mixtures of letters and numerals
\ReplaceOff % no more infix to frac processing
\[ m /n + pq/rs = 1 / 2 - 21/32 . \]
\end{document}
附录:要将 Lua 函数的范围自动扩展到整个文档,需要执行一些测试来检查我们是否处于显示数学环境中,并且仅在处于这种情况时才执行中缀到小数的转换。以下示例显示了如何执行此操作。除了“基本 LaTeX”\[
和\]
命令外,还会自动识别六个显示数学环境:equation
、、、、、和。这些环境的“带星align
号”和“常规”变体均可处理。alignat
flalign
gather
multline
对输入语法的要求相当宽松。\[ ... \]
允许使用带有 的表达式,以及所有显示数学环境,其中开头和结尾语句(例如\begin{equation}
或\end{align}
)单独成行。
下面的代码还提供了宏\ReplaceOff
和\ReplaceOn
,因为可能需要“手动”暂停 Lua 函数的操作,比如,在verbatim
包含 displaymath 代码的类似材料的情况下。
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{amsmath} % for various displayed-equation environments
%% Lua-side code
\usepackage{luacode}
\begin{luacode*}
in_dispmath = false -- set up a Boolean variable
function sltofr ( s ) -- "slash to frac"
-- if we find a '\[ ... \]' line, perform infix fraction replacements
if string.find ( s , "\\%[.*\\%]" ) then
return ( string.gsub ( s , "(%w+)%s-/%s-(%w+)" , "\\frac{%1}{%2}" ) )
-- switch 'in_dispmath' to 'true' if at start of a displaymath env.
elseif string.find ( s , "\\begin{equation%*?}" ) or
string.find ( s , "\\begin{align%*?}" ) or
string.find ( s , "\\begin{alignat%*?}" ) or
string.find ( s , "\\begin{flalign%*?}" ) or
string.find ( s , "\\begin{gather%*?}" ) or
string.find ( s , "\\begin{multline%*?}" ) or
string.find ( s , "\\%[" ) then
in_dispmath = true
-- switch 'in_dispmath' back to 'false' if at end of a displaymath env.
elseif string.find ( s , "\\end{equation%*?}" ) or
string.find ( s , "\\end{align%*?}" ) or
string.find ( s , "\\end{alignat%*?}" ) or
string.find ( s , "\\end{flalign%*?}" ) or
string.find ( s , "\\end{gather%*?}" ) or
string.find ( s , "\\end{multline%*?}" ) or
string.find ( s , "\\%]" ) then
in_dispmath = false
-- if in displaymath mode, replace infix fractions with \frac expressions
elseif in_dispmath == true then
return ( string.gsub ( s , "(%w+)%s-/%s-(%w+)" , "\\frac{%1}{%2}" ) )
end
end
\end{luacode*}
%% TeX-side code
% Assign the Lua function to the 'process_input_buffer' callback
\AtBeginDocument{\directlua{luatexbase.add_to_callback (
"process_input_buffer", sltofr, "sltofr" )}}
% Macros to enable and disable the Lua function "by hand";
% this may be needed if the document contains verbatim sections
% that feature displaymath-mode code
\newcommand\ReplaceOn{\directlua{luatexbase.add_to_callback (
"process_input_buffer", sltofr, "sltofr" )}}
\newcommand\ReplaceOff{\directlua{luatexbase.remove_from_callback (
"process_input_buffer", "sltofr" )}}
\begin{document}
\[ 2m /3n + pq / rs = 1 / 2 - 33/ 55 . \]
\[
2m/3n+pq/rs=1/2-33/55.
\]
\[1/2+1/2=1\]\[1/3+1/3+1/3=1\]
\begin{align*}
1/2+1/2 &=1\\
1/3+1/3 + 1 / 3 &= 1
\end{align*}
When not in display math mode, no processing: ``and/or'', $a/b$, $1/2$
\ReplaceOff % get ready for some verbatim material
\begin{verbatim}
\begin{align*}
1/2+1/2 &=1\\
1/3+1/3 + 1 / 3 &= 1
\end{align*}
\end{verbatim}
\ReplaceOn % back to 'normal' (replacement) mode
\begin{align*}
1/2+1/2 &=1\\
1/3+1/3 + 1 / 3 &= 1
\end{align*}
\end{document}
答案2
如果提供的文件保存为f.tex
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\begin{document}
\[ m/n + p/q = 2/3 . \]
I want
\[\dfrac{m}{n} + \dfrac{p}{q} = \dfrac{2}{3}.\]
\end{document}
然后
sed -e "s@ \([a-zA-Z0-9]\+\)/\([a-zA-Z0-9]\+\) @ \\\\dfrac{\\1}{\\2} @g" f1.tex > f2.tex
将产生
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\begin{document}
\[ \dfrac{m}{n} + \dfrac{p}{q} = \dfrac{2}{3} . \]
I want
\[\dfrac{m}{n} + \dfrac{p}{q} = \dfrac{2}{3}.\]
\end{document}
sed
在类 unix 系统(linux、macos、cygwin……)中默认可用,并且可在 windows 的许多地方使用。
如果不需要命令行 sed,也可以在任何文本编辑器中执行相同的正则表达式替换。