从技术上讲,这不是一个特定于 LaTeX 的问题,但是 LaTeX 中有很多有用的工具,而且我正在用它来解决 LaTeX 问题,所以我认为这里是个提问的好地方。
我有一个相当大的文档,其中包含大量数学符号。我|foo|
始终使用 来表示 foo 的绝对值。我想用 替换每个 实例|foo|
,\abs{foo}
以便我可以通过我定义的 abs 宏来控制符号。
有人知道怎么做吗?可能使用某种正则表达式吗?有没有内置工具的编辑器?
答案1
选项1:sed
流编辑工具,,sed
自然是首选,但问题是sed
无法匹配非贪婪常用表达。
这里我们需要一个非贪婪的正则表达式——为了阐明原因,让我们考虑一下
sed -r 's/|(.*)|/\\abs{\1}/g' myfile.tex
如果我们将这个替换应用到包含类似以下内容的文件
$|a|+|b|\geq|a+b|$
那么我们就会得到
$\abs{a|+|b|\geq|a+b}$
这显然不是我们想要的是-像这样的正则表达式匹配贪婪的默认情况下。
为了使其非贪婪,我们通常使用.*?
,但问题sed
是不支持此类匹配。很高兴(感谢 Hendrik),我们可以使用以下内容
sed -r 's/\|([^|]*)\|/\\abs{\1}/g' myfile.tex
一旦你确信它可以满足你的要求,你就可以使用
sed -ri.bak 's/\|([^|]*)\|/\\abs{\1}/g' myfile.tex
它将覆盖每个文件,并首先进行备份,myfile.tex.bak
选项 2:perl
我们可以使用一行小perl
代码:
perl -pe 's/\|(.*?)\|/\\abs{\1}/g' myfile.tex
当你在当然如果你相信它正常工作,你可以使用以下命令覆盖 myfile.tex
perl -pi -e 's/\|(.*?)\|/\\abs{\1}/g' myfile.tex
myfile.tex
例如,你可以替换为,对当前工作目录中的*.tex
所有文件进行操作 。.tex
有关 开关的详细信息perl
在此处讨论(例如):http://perldoc.perl.org/perlrun.html#命令开关
答案2
\documentclass{article}
\begin{document}
\def\abs#1{|#1|} % Let us assume that it is your definition
$\abs{c+d}$
\catcode`\|=\active
\def|#1|{\abs{#1}}
$|a|+|b|\geq|a+b|$
\end{document}
我们假设|
是成对的。那么第一个成为定义,第二个成为论证的结束。然而,似乎对于所有其他解决方案,都需要手动更正。
答案3
您也可以尝试 WinEdt。它具有非常完善的“搜索和替换”功能。
在你的情况下,搜索(使用正则表达式)
\|\(0*\)\|
并替换为
\\abs\{\0\}
整个替换过程只需一步即可完成。
您还可以选择(使用不同的正则表达式)仅在数学环境中进行替换。
答案4
这篇文章的灵感来自于休斯建议的解决方案。他的帖子是我读过的关于 TeX 编辑的最有趣的帖子之一。我刚刚花了 2 个小时尝试制作实际上不存在的 nawk 解决方案(见下文)。
选项 3:Gawk
此解决方案由亨德里克·沃格特
gawk '{print gensub(/\|([^|]*)\|/, "\\abs{\\1}", "g", $0)}'
选项 4:Python
import sys
import re
file = sys.stdin.readlines()
for line in file:
newline = re.sub('\|(.*?)\|', '\\\\abs{\\1}', line)
sys.stdout.write(newline)
为什么 AWK(nawk)不是解决上述问题的错误工具?
AWK 不支持非贪婪正则表达式,这是意料之中的,因为它是 sed 的堂兄,但更糟糕的是,AWK 正则表达式不捕获其组。即使 AWK 支持组捕获,我们也会遇到麻烦,因为反向引用 不能在室内使用字符类并且我们使用字符类来实现 AWK 中的非贪婪性。
一个简单的 AWK 脚本
NR>0{
gsub(/\|([^|]*)\|/,"\\abs{\1}")
print
}
已申请立案
$|abs|$ so on and so fourth
$$|a|+|b|\geq|a+b|$$
who is affraid of wolf $|abs|$
不幸会产生
$\abs{}$ so on and so fourth
$$\abs{}+\abs{}\geq\abs{}$$
who is affraid of wolf $\abs{}$