我想用 LaTeXish 和 替换 tex 文件中的所有 TeXish 数学。我$ $
该如何巧妙地做到这一点?\( \)
$$ $$
\[ \]
请注意,在 TikZ 环境中,不能用$ $
替换\( \)
。
答案1
这是一个perl
帮助您入门的脚本subDollars.pl
。作为免责声明,您应该在将其用于任何重要的事情之前对其进行大量测试。我无法保证结果,但它应该可以帮助您入门。
你可以通过以下方式使用它
perl subDollars.pl test.tex
将简单地输出到终端并替换perl subDollars.pl -s test.tex
不会输出到终端perl subDollars.pl -w test.tex
test.tex
将用替换内容覆盖perl subDollars.pl -o test.tex output.tex
将输出output.tex
替换后的版本。
您不希望它操作应该包括在
my %nosubstitutions = ("tikzpicture"=>1, "verbatim"=>1, "nosubblock"=>1);
该哈希可以由以下标准环境组成tikzpicture
\begin{tikzpicture}
\draw[red] ($(#2)+(-.5em,.9em)$) rectangle ($(RightPoint)+(0.2em,-0.3em)$);
\end{tikzpicture}
或者任何不一定在环境中的代码块,但你可以将它们包装在“注释”环境中,例如
%\begin{nosubblock}
\draw[red] ($(#2)+(-.5em,.9em)$) rectangle ($(RightPoint)+(0.2em,-0.3em)$);
%\end{nosubblock}
脚本不会考虑$...$
跨行$$...$$
分割 - 这当然是可行的,但需要做更多的工作。
subDollars.pl
#!/usr/bin/perl
use strict;
use warnings;
use File::Copy; # to copy the original file to backup (if overwrite option set)
use Getopt::Std; # to get the switches/options/flags
# get the options
my %options=();
getopts("wos", \%options);
# standard output
my $out = *STDOUT;
# overwrite option
my $overwrite = 0;
$overwrite = $options{w};
# output file option
my $outputToFile = $options{o};
# can't call the script with MORE THAN 2 files
if(scalar(@ARGV)>2)
{
print $out <<ENDQUOTE
ERROR:
\t You're calling subDollars.pl with more than two file names
\t The script can take at MOST two file names, but you
\t need to call it with the -o switch; for example
\t subDollars.pl -o originalfile.tex outputfile.tex
Exiting...
ENDQUOTE
;
exit(2);
}
# check for output file
if($outputToFile and scalar(@ARGV)==1)
{
print $out <<ENDQUOTE
ERROR: When using the -o flag you need to call this script with 2 arguments
subDollars.pl -o "$ARGV[0]" [needs another name here]
Exiting...
ENDQUOTE
;
exit(2);
}
# don't call the script with 2 files unless the -o flag is active
if(!$outputToFile and scalar(@ARGV)==2)
{
print $out <<ENDQUOTE
ERROR:
\t You're calling subDollars.pl with two file names, but not the -o flag.
\t Did you mean to use the -o flag ?
Exiting...
ENDQUOTE
;
exit(2);
}
# array to store the modified lines
my @lines;
# hash naming environments that contain lines
# that should not be substituted
my %nosubstitutions = ("tikzpicture"=>1, "verbatim"=>1, "nosubblock"=>1);
# switch to toggle nosubstitutions- initially off
my $nosubs = 0;
# if we want to over write the current file
# create a backup first
if ($overwrite)
{
# original name of file
my $filename = $ARGV[0];
# copy it
my $backupFile = $filename;
my $backupExtension='.bak';
$backupFile =~ s/\.tex/$backupExtension/;
copy($filename,$backupFile) or die "Could not write to backup file $backupFile. Please check permissions. Exiting.\n";
}
# open the file
open(MAINFILE, $ARGV[0]) or die "Could not open input file";
# loop through the lines in the INPUT file
while(<MAINFILE>)
{
# check for BEGIN of an environment that doesn't want substitutions
$nosubs = 1 if( $_ =~ m/^\s*\\begin{(.*?)}/ and $nosubstitutions{$1} );
# check for %\begin{nosubblock}
$nosubs = 1 if( $_ =~ m/^\s*%\s*\\begin{(.*?)}/ and $nosubstitutions{$1} );
# check for END of an environment that doesn't want substitutions
$nosubs = 0 if( $_ =~ m/^\s*\\end{(.*?)}/ and $nosubstitutions{$1});
# check for %\end{nosubblock}
$nosubs = 0 if( $_ =~ m/^\s*%\s*\\end{(.*?)}/ and $nosubstitutions{$1} );
# substitute $.*$ with \(.*\)
# note: this does NOT match $$.*$$
s/(?<!\$)\$([^\$].*?)\$/\\\($1\\\)/g unless($nosubs);
# substitute $$.*$$ with \[.*\]
s/\$\$(.*?)\$\$/\\\[$1\\\]/g unless($nosubs);
push(@lines,$_);
}
# output the formatted lines to the terminal
print @lines if(!$options{s});
# if -w is active then output to $ARGV[0]
if($overwrite)
{
open(OUTPUTFILE,">",$ARGV[0]);
print OUTPUTFILE @lines;
close(OUTPUTFILE);
}
# if -o is active then output to $ARGV[1]
if($outputToFile)
{
open(OUTPUTFILE,">",$ARGV[1]);
print OUTPUTFILE @lines;
close(OUTPUTFILE);
}
exit;
这是一个测试文件来测试它
before.tex
\documentclass{article}
\begin{document}
$x=a+b$
$x=a+b$ and another $x=a+b$, $x=a+b$ and another $x=a+b$
$$x=a+b$$ and another $$x=a+b$$, $$x=a+b$$ and another $$x=a+b$$
\begin{tikzpicture}
\draw[red] ($(#2)+(-.5em,.9em)$) rectangle ($(RightPoint)+(0.2em,-0.3em)$);
\end{tikzpicture}
\begin{verbatim}
\draw[red] ($(#2)+(-.5em,.9em)$) rectangle ($(RightPoint)+(0.2em,-0.3em)$);
\end{verbatim}
$$x=a+b$$ and another $$x=a+b$$, $$x=a+b$$ and another $$x=a+b$$
%\begin{nosubblock}
\draw[red] ($(#2)+(-.5em,.9em)$) rectangle ($(RightPoint)+(0.2em,-0.3em)$);
%\end{nosubblock}
$x=a+b$ and another $x=a+b$, $x=a+b$ and another $x=a+b$
$$x=a+b$$ and another $$x=a+b$$, $$x=a+b$$ and another $$x=a+b$$
\end{document}
after.tex
\documentclass{article}
\begin{document}
\(x=a+b\)
\(x=a+b\) and another \(x=a+b\), \(x=a+b\) and another \(x=a+b\)
\[x=a+b\] and another \[x=a+b\], \[x=a+b\] and another \[x=a+b\]
\begin{tikzpicture}
\draw[red] ($(#2)+(-.5em,.9em)$) rectangle ($(RightPoint)+(0.2em,-0.3em)$);
\end{tikzpicture}
\begin{verbatim}
\draw[red] ($(#2)+(-.5em,.9em)$) rectangle ($(RightPoint)+(0.2em,-0.3em)$);
\end{verbatim}
\[x=a+b\] and another \[x=a+b\], \[x=a+b\] and another \[x=a+b\]
%\begin{nosubblock}
\draw[red] ($(#2)+(-.5em,.9em)$) rectangle ($(RightPoint)+(0.2em,-0.3em)$);
%\end{nosubblock}
\(x=a+b\) and another \(x=a+b\), \(x=a+b\) and another \(x=a+b\)
\[x=a+b\] and another \[x=a+b\], \[x=a+b\] and another \[x=a+b\]
\end{document}
答案2
你可能想看看这个线。这至少应该能给你一个良好的起点。但是,如果$ $
和$$ $$
分布在多行上,则线程中的解决方案将需要进行重大修改。您还在谈论 TikZ 代码的例外情况。这将进一步使其成为正则表达式中非常有趣的练习。我个人倾向于使用 Python 来解决这个问题,但 Perl 绝对是做这项工作的正确选择。sed 解决方案必须非常巧妙,因为 sed 通常在单行上运行并且只使用基本的 Posix 正则表达式。任何多行 sed 编辑都被认为是非常高级的东西。对于这个特定问题,我会避免使用 awk。
答案3
很明显,最适合此目的的语言是 Emacs Lisp。事实上,我有一个可行的解决方案(虽然没有考虑到tikz
,这是一个有趣的问题;而且,$a$$b$
会让它绊倒 - 但它是为现实生活而设计的,而不是学术界;))。它不是好的,惯用的 Elisp(可能),但应该可以正常工作(我会在某一天让它变得更好......)此外,它更通用 - 它还处理波兰变音符号,并且通常能够用循环替换列表替换给定的正则表达式(尽管单和双美元符号是目前唯一的应用)。如上所述,它不是万无一失的,但我已在来自各种来源的真实文档上使用它,并且绝不遇到了问题。(现在我明白这是\$
行不通的;扩展正则表达式来处理这个问题留给读者作为练习;)。)
(defcustom amrr-pattern-list
'(("\\$\\$" "\\\\[" "\\\\]")
("\\$" "\\\\(" "\\\\)")
("\\\\[ck] +a\\|{\\\\[ck] +a}\\|\\\\[ck] *{a}" "ą")
("\\\\'c\\|{\\\\'c}\\|\\\\'{c}" "ć")
("\\\\[ck] +e\\|{\\\\[ck] +e}\\|\\\\[ck] *{e}" "ę")
("\\\\l +\\|{\\\\l}\\|\\\\l{}" "ł")
("\\\\'n\\|{\\\\'n}\\|\\\\'{n}" "ń")
("\\\\'o\\|{\\\\'o}\\|\\\\'{o}" "ó")
("\\\\'s\\|{\\\\'s}\\|\\\\'{s}" "ś")
("\\\\'z\\|{\\\\'z}\\|\\\\'{z}" "ź")
("\\\\\\.z\\|{\\\\\\.z}\\|\\\\\\.{z}" "ż")
("\\\\[ck] +A\\|{\\\\[ck] +A}\\|\\\\[ck] *{A}" "Ą")
("\\\\'C\\|{\\\\'C}\\|\\\\'{C}" "Ć")
("\\\\[ck] +E\\|{\\\\[ck] +E}\\|\\\\[ck] *{E}" "Ę")
("\\\\L +\\|{\\\\L}\\|\\\\L{}" "Ł")
("\\\\'N\\|{\\\\'N}\\|\\\\'{N}" "Ń")
("\\\\'O\\|{\\\\'O}\\|\\\\'{O}" "Ó")
("\\\\'S\\|{\\\\'S}\\|\\\\'{S}" "Ś")
("\\\\'Z\\|{\\\\'Z}\\|\\\\'{Z}" "Ź")
("\\\\\\.Z\\|{\\\\\\.Z}\\|\\\\\\.{Z}" "Ż"))
"A list of patterns for the amrr-replace function. Each entry is a
list. The car of each list is a regexp to be found; the cdr is a list
of replacement variants. They will be used in succession: the nth of
them will be used on the nth match, cycling modulo the number of them
if necessary.")
(defmacro advance (list)
`(setq ,list (cdr ,list)))
(defmacro cycle (position list)
`(prog1
(advance ,position)
(when (null ,position)
(setq ,position ,list))))
(defvar amrr-replacement-list)
(defvar amrr-current-replacement)
(defun amrr-replace (beg end)
"Replace all patterns according to amrr-pattern-list (in region if
it is present)."
(interactive (if (use-region-p)
(list (region-beginning) (region-end))
(list (point-min) (point-max))))
(goto-char beg)
(dolist (pattern amrr-pattern-list)
(setq amrr-replacement-list (cdr pattern)
amrr-current-replacement amrr-replacement-list)
(while (let (old-cfs case-fold-search)
(prog2
(setq case-fold-search nil)
(re-search-forward
(car pattern)
end
t)
(setq case-fold-search old-cfs)))
(replace-match (car amrr-current-replacement) t)
(cycle amrr-current-replacement amrr-replacement-list))
(goto-char beg)))