客观的:
我正在尝试输入文件内容的存在(评论是可以接受的,我正在尝试输入将在构建的 PDF 中显示的内容)来确定要采取什么路径。
如果 .tex 文件具有可显示的内容,则执行 ActionA。如果 .tex 文件实际上是空的(只有注释和空行),则执行 ActionB。
我拥有的:
\documentclass[12pt]{book}
\usepackage{catchfile}
\usepackage{ifthen}
\begin{document}
\newcommand{\isFileEmpty}[1]{
\setbox0=\hbox{#1\unskip}\ifdim\wd0=0pt%
\boolean{true}%
\else
\boolean{false}%
\fi
}
\CatchFileDef\filecontent{catchfile}{}%
Macro test line: \isFileEmpty\expandafter{\filecontent }
\ifthenelse{\isFileEmpty\expandafter{\filecontent }}% <-- This is where the error occurs
{Do stuff with file}
{Do something else}
\end{document}
示例 my_tex_file.tex 内容如下:
%% commented line
Actual text
示例空白my_tex_file.tex:
%% Commented line
我看到的错误是:
<to be read again>
\setbox
l.106 ...ifthenelse{ \isFileEmpty{\filecontent }}
! ==> Fatal error occured, no output PDF produced!
参考:
我一直在参考https://archive.org/details/B-001-002-139/page/n383/mode/2up和https://www.overleaf.com/learn/latex/Articles/How_does_%5Cexpandafter_work:_An_introduction_to_TeX_tokens
我所在的位置:
我相信我可以使用额外的\expandafter
s 来实现这一点,但我一直没有成功。我理解 的基本概念,\expandafter
但我缺乏让这个特定用例发挥作用的经验。
任何帮助实现此方法的帮助都将不胜感激。任何替代此方法的方法也同样值得感激。
在此先感谢您的帮助。
答案1
您的示例中的-test\isFileEmpty
似乎旨在将捕获到的宏放入一个盒子中,并测量该盒子的宽度,如果宽度为 0,则“假定”为空。
此类测试可能会被欺骗/被识破,例如,通过放置包含可显示内容的深度/高度/宽度 0pt 的过满框:
\documentclass{article}
\usepackage{ifthen}
\usepackage{catchfile}
\begin{filecontents*}{filetocatch.tex}
\newbox\mybox
\setbox\mybox=\vbox{\hbox{Hello, world!}\hbox{Hello, world!}\hbox{Hello, world!}}%
\wd\mybox=0pt %
\ht\mybox=0pt %
\dp\mybox=0pt %
\box\mybox
\end{filecontents*}
\newboolean{IsFileEmpty}%
\newcommand{\isFileEmpty}[1]{%
\setbox0=\hbox{#1\unskip}%
\ifdim\wd0=0pt%
\setboolean{IsFileEmpty}{true}%
\else
\setboolean{IsFileEmpty}{false}%
\fi
\ifthenelse{\boolean{IsFileEmpty}}%
}%
\parindent=0ex
\parskip=\baselineskip
\begin{document}
This is the result of the emptiness-test after catching the content
of the file \verb|filetocatch.tex| into the macro \verb|\filecontent|:
\CatchFileDef{\filecontent}{filetocatch.tex}{}%
\isFileEmpty{\filecontent}{File is empty!}{File is not empty!}
\bigskip
This is the result of carrying out the macro \verb|\filecontent|:
\filecontent
\end{document}
浮点数也可能是一个问题:
\documentclass{article}
\usepackage{ifthen}
\usepackage{catchfile}
\begin{filecontents*}{filetocatch.tex}
\begin{figure}[h]
This is a figure.
\caption{This is the figure's caption.}
\end{figure}
\end{filecontents*}
\newboolean{IsFileEmpty}%
\newcommand{\isFileEmpty}[1]{%
\setbox0=\hbox{#1\unskip}%
\ifdim\wd0=0pt%
\setboolean{IsFileEmpty}{true}%
\else
\setboolean{IsFileEmpty}{false}%
\fi
\ifthenelse{\boolean{IsFileEmpty}}%
}%
\parindent=0ex
\parskip=\baselineskip
\begin{document}
\listoffigures
\CatchFileDef{\filecontent}{filetocatch.tex}{}%
This is the result of carrying out the macro \verb|\filecontent|:
\filecontent
\bigskip
Carrying out the emptiness-test after catching the content
of the file \verb|filetocatch.tex| into the macro \verb|\filecontent|
leads to an error-message on the terminal/console:
\verb|! LaTeX Error: Not in outer par mode.|
Subsequent error-messages follow.
Besides this you erroneously get as result:
\isFileEmpty{\filecontent}{File is empty!}{File is not empty!}
\end{document}
逐字逐句(verbatim
-environments/ \verb|...|
-commands)对于-test来说也会是个问题\isFileEmpty
:
\documentclass{article}
\usepackage{ifthen}
\usepackage{catchfile}
\begin{filecontents*}{filetocatch.tex}
\begin{verbatim}
This is verbatim
\end{verbatim}
\end{filecontents*}
\newboolean{IsFileEmpty}%
\newcommand{\isFileEmpty}[1]{%
\setbox0=\hbox{#1\unskip}%
\ifdim\wd0=0pt%
\setboolean{IsFileEmpty}{true}%
\else
\setboolean{IsFileEmpty}{false}%
\fi
\ifthenelse{\boolean{IsFileEmpty}}%
}%
\parindent=0ex
\parskip=\baselineskip
\begin{document}
\CatchFileDef{\filecontent}{filetocatch.tex}{}%
% Carrying out the emptiness-test after catching the content
% of the file filetocatch.tex into the macro \filecontent
% leads to error-messages on the terminal/console.
%
% \verb|! LaTeX Error: Something's wrong--perhaps a missing \item.|
%
% Subsequent error-messages follow.
%
% You get neither a result nor a proper output-file/.pdf-file
% because LaTeX does not leave verbatim-mode and therefore
% does not even find the \end{document}-directive.
%
\isFileEmpty{\filecontent}{File is empty!}{File is not empty!}
\end{document}
如果您想知道文件中是否存在除空格字符、换行符(通常是 Return / CR 或 CR+LF)和以 开头的行以外的其他字符%
,您可以切换到 verbatim-catcode-régime 并通过 的第三个参数将整数参数切换\endlinechar
为负值\CatchFileDef
。
这不是可显示内容的测试。这是可标记化以供 TeX 进一步处理的内容的测试,该内容由空格字符/换行符/空行/注释行以外的内容组成。
\documentclass{article}
\usepackage{catchfile}
\usepackage{listings} % Used only for displaying files
\lstset{numbers=left, numberstyle=\tiny, numbersep=5pt,
basicstyle=\ttfamily, language={}, frame=single}
\begin{filecontents*}{filetocatchA.tex}
This is some content.
\end{filecontents*}
\begin{filecontents*}{filetocatchB.tex}
% This is some comment
% This is some comment
%
\end{filecontents*}
\begin{filecontents*}{filetocatchC.tex}
\newbox\mybox
\setbox\mybox=\vbox{%
\hbox{Hello, world!}%
\hbox{Hello, world!}%
\hbox{Hello, world!}%
}%
\wd\mybox=0pt %
\ht\mybox=0pt %
\dp\mybox=0pt %
\box\mybox
\end{filecontents*}
\begin{filecontents*}{filetocatchD.tex}
\begin{figure}[h]
This is a figure.
\caption{This is the figure's caption.}
\end{figure}
\end{filecontents*}
\begin{filecontents*}{filetocatchE.tex}
{\def\empty{}\empty\empty\empty}%
\end{filecontents*}
\begin{filecontents*}{filetocatchF.tex}
}}}}{{{
Unbalanced braces.
\end{filecontents*}
\makeatletter
%%-----------------------------------------------------------------------------
%% Check whether argument contains no tokens/is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked contains no tokens/is
%% empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked contains some tokens/
%% is not empty>}%
%%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
%%
%% The way in which this macro works is explained in my answer to the
%% TeX-LaTeX-StackExchange-Question "Expandable test for an empty token
%% list—methods, performance, and robustness" at
%% <https://tex.stackexchange.com/a/522506>
%% In that answer it is named \CheckWhetherEmpty.
\newcommand\UD@CheckWhetherNull[1]{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\@firstoftwo\expandafter{} \@secondoftwo}%
{\@firstoftwo\expandafter{} \@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Check whether argument is blank (empty/no tokens at all or only
%% explicit space tokens (character code 32/category code 10)):
%%-----------------------------------------------------------------------------
%% -- Take advantage of the fact that TeX discards space tokens when
%% "fetching" _un_delimited arguments: --
%% \UD@CheckWhetherBlank{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that
%% argument which is to be checked is blank>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not blank>}%
\newcommand\UD@CheckWhetherBlank[1]{%
\romannumeral\expandafter\expandafter\expandafter\@secondoftwo
\expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo#1{}.}%
}%
\newcommand{\isFileEmpty}[1]{%
\begingroup
\CatchFileDef{\filecontent}{#1}{%
\let\do\@makeother
\dospecials
\catcode`\%=14 %
\catcode`\ =10 %
\catcode`\^^I=12 %
\endlinechar=-1 %
}%
\expandafter\endgroup
\expandafter\UD@CheckWhetherBlank
\expandafter{\filecontent}%
}%
\makeatother
\parindent=0ex
\parskip=\baselineskip
\begin{document}
This is the content of \verb|filetocatchA.tex|:
\lstinputlisting{filetocatchA.tex}
This is the result of the empty-test:
\isFileEmpty{filetocatchA.tex}{File is empty!}{File is not empty!}
\leavevmode\hrule height .5\ht\strutbox\hfill
This is the content of \verb|filetocatchB.tex|:
\lstinputlisting{filetocatchB.tex}
This is the result of the empty-test:
\isFileEmpty{filetocatchB.tex}{File is empty!}{File is not empty!}
\leavevmode\hrule height .5\ht\strutbox\hfill
This is the content of \verb|filetocatchC.tex|:
\lstinputlisting{filetocatchC.tex}
This is the result of the empty-test:
\isFileEmpty{filetocatchC.tex}{File is empty!}{File is not empty!}
\leavevmode\hrule height .5\ht\strutbox\hfill
This is the content of \verb|filetocatchD.tex|:
\lstinputlisting{filetocatchD.tex}
This is the result of the empty-test:
\isFileEmpty{filetocatchD.tex}{File is empty!}{File is not empty!}
\leavevmode\hrule height .5\ht\strutbox\hfill
This is the content of \verb|filetocatchE.tex|:
\lstinputlisting{filetocatchE.tex}
This is the result of the empty-test:
\isFileEmpty{filetocatchE.tex}{File is empty!}{File is not empty!}
\leavevmode\hrule height .5\ht\strutbox\hfill
This is the content of \verb|filetocatchF.tex|:
\lstinputlisting{filetocatchF.tex}
This is the result of the empty-test:
\isFileEmpty{filetocatchF.tex}{File is empty!}{File is not empty!}
\end{document}