subDollars.pl

subDollars.pl

我想用 LaTeXish 和 替换 tex 文件中的所有 TeXish 数学。我$ $该如何巧妙地做到这一点?\( \)$$ $$\[ \]

请注意,在 TikZ 环境中,不能用$ $替换\( \)

答案1

这是一个perl帮助您入门的脚本subDollars.pl。作为免责声明,您应该在将其用于任何重要的事情之前对其进行大量测试。我无法保证结果,但它应该可以帮助您入门。

你可以通过以下方式使用它

  • perl subDollars.pl test.tex将简单地输出到终端并替换
  • perl subDollars.pl -s test.tex不会输出到终端
  • perl subDollars.pl -w test.textest.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)))

答案4

使用 VS Code“查找和替换”

您可以使用编辑器来完成此操作。

替换$math$\(math\)

  • 寻找:(\$)([^$\r]+)(\$)
  • 代替:\($2\)

替换$$math$$\[math\]

  • 寻找:(\$\$)([^$\r]+)(\$\$)
  • 代替:\[$2\]

请参阅 regex101 了解解释

\r为了多行VS Code 中的数学。

VS Code 中的使用示例

相关内容