我有一个 shell 脚本,它在外部文件中生成大量宏列表,其形式如下:
\expandafter\newcommand\csname XX Name ABC\endcsname{some text ABC 1}
\expandafter\newcommand\csname XX Name XYX\endcsname{some text XYX a}
\expandafter\newcommand\csname XX Name XYZ\endcsname{some text XYZ}
...
宏的名称基于各个目录中的文件名。由于文件位于不同的目录中,因此它们可以具有相同的名称,在这种情况下 TeX 会出现问题并停止在第一个重复的宏上。
我想通过重新定义来检测重复项并提供这些重复项的完整列表\newcommand
。 但是,我的尝试存在一些问题:
- 它不起作用——所有内容都被报告为重复。
- 的定义文本
\newcommand
打印在文档中。希望它不出现在那里,因为它没有任何价值。我可以接受输出中的这段文本,只是不明白它是怎么到达那里的。
代码:
\documentclass{article}
\usepackage{etoolbox}
%\usepackage{filecontents}% <--- Commented so that foo.tex is not accidentally overwritten.
\begin{filecontents*}{foo.tex}
\expandafter\newcommand\csname XX Name ABC\endcsname{some text ABC 1}
\expandafter\newcommand\csname XX Name XYX\endcsname{some text XYX a}
\expandafter\newcommand\csname XX Name XYZ\endcsname{some text XYZ}
\expandafter\newcommand\csname XX Name ABC\endcsname{some text ABC 2}
\expandafter\newcommand\csname XX Name XYX\endcsname{some text XYX b}
\end{filecontents*}
\newcounter{ErrorCount}
\let\OldNewcommand\newcommand
\begin{document}
\renewcommand*{\newcommand}[2][]{%
\ifdefined#2
\stepcounter{ErrorCount}%
\typeout{**** Error: "#1" is a duplicate.}%
\par Error: ``#1" is a duplicate
\else
\OldNewcommand[#1]{#2}%
\fi
% \ifcsname{#2}{%
% \stepcounter{ErrorCount}%
% \typeout{**** Error: "#1" is a duplicate.}%
% \par Error: ``#1" is a duplicate
% }{%
% \OldNewcommand[#1]{#2}%
% }%
}%
% -------------
\input{foo.tex}
\let\newcommand\OldNewcommand
% -------------
\ifnum\arabic{ErrorCount}=0
\typeout{**** Error: 0.}%
\par All good. No errors.
\else
\typeout{**** Error: Duplicates found.}%
\par Error: \arabic{ErrorCount} duplicates found.
\fi
\end{document}
答案1
latex 已经在进行检查,因此只需将错误更改为警告并增加:
\documentclass{article}
%\usepackage{filecontents}% <--- Commented so that foo.tex is not accidentally overwritten.
\begin{filecontents*}{foo.tex}
\expandafter\newcommand\csname XX Name ABC\endcsname{some text ABC 1}
\expandafter\newcommand\csname XX Name XYX\endcsname{some text XYX a}
\expandafter\newcommand\csname XX Name XYZ\endcsname{some text XYZ}
\expandafter\newcommand\csname XX Name ABC\endcsname{some text ABC 2}
\expandafter\newcommand\csname XX Name XYX\endcsname{some text XYX b}
\end{filecontents*}
\makeatletter
\gdef\@notdefinable{%
\stepcounter{ErrorCount}%
\@latex@warning@no@line{%
Command \@backslashchar\reserved@a\space
already defined.\MessageBreak
Or name \@backslashchar\@qend... illegal,
see p.192 of the manual}}
%\makeatother
\newcounter{ErrorCount}
\begin{document}
% -------------
\input{foo.tex}
\let\newcommand\OldNewcommand
% -------------
\ifnum\value{ErrorCount}=0
\typeout{**** Error: 0.}%
\par All good. No errors.
\else
\typeout{**** Error: Duplicates found.}%
\par Error: \theErrorCount{} duplicates found.
\fi
\end{document}
答案2
我使用了\@namedef
而不是。让生活更轻松。如果您确实需要 at 符号,\expandafter\csname...
也可以设置:\let\namedef\@namedef
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents*}{foo.tex}
\@namedef{XX Name ABC}{some text ABC 1}
\@namedef{XX Name XYX}{some text XYX a}
\@namedef{XX Name XYZ}{some text XYZ}
\@namedef{XX Name ABC}{some text ABC 2}
\@namedef{XX Name XYX}{some text XYX b}
\end{filecontents*}
\newcounter{ErrorCount}
\makeatletter
\let\Old@namedef\@namedef
\def\@namedef#1#2{%
\if\@nameuse{#1}\relax
\Old@namedef{#1}{#2}
\else
\stepcounter{ErrorCount}%
\typeout{**** Error: "#1" is a duplicate.}%
\par Error: ``#1" is a duplicate
\fi
}
\makeatother
\begin{document}
\makeatletter
\input{foo.tex}
\makeatother
\ifnum\arabic{ErrorCount}=0
\typeout{**** Error: 0.}%
\par All good. No errors.
\else
\typeout{**** Error: Duplicates found.}%
\par Error: \arabic{ErrorCount} duplicates found.
\fi
\end{document}
答案3
好吧,你可以从内核借用一些代码,其主要思想是将命令名称捕获为字符串。
\documentclass{article}
\usepackage{etoolbox}
\usepackage{filecontents}
\begin{filecontents*}{foo.tex}
\expandafter\newcommand\csname XX Name ABC\endcsname{some text ABC 1}
\expandafter\newcommand\csname XX Name XYX\endcsname{some text XYX a}
\expandafter\newcommand\csname XX Name XYZ\endcsname{some text XYZ}
\expandafter\newcommand\csname XX Name ABC\endcsname{some text ABC 2}
\expandafter\newcommand\csname XX Name XYX\endcsname{some text XYX b}
\end{filecontents*}
\newcounter{ErrorCount}
\let\OldNewcommand\newcommand
\begin{document}
\makeatletter
\renewcommand*{\newcommand}[2]{%
\begingroup \escapechar\m@ne\xdef\@mytempa{{\string#1}}\endgroup
\expandafter\@ifundefined\@mytempa
{OK \OldNewcommand{#1}{#2}%
}{\stepcounter{ErrorCount}%
\typeout{**** Error: "\string#1" is a duplicate.}%
\par Error: ``\string#1" is a duplicate
}%
}%
\makeatother
% -------------
\input{foo.tex}
\let\newcommand\OldNewcommand
% -------------
\ifnum\arabic{ErrorCount}=0
\typeout{**** Error: 0.}%
\par All good. No errors.
\else
\typeout{**** Error: Duplicates found.}%
\par Error: \arabic{ErrorCount} duplicates found.
\fi
\end{document}
我不确定你的可选参数的作用是什么。