在 \write18 中展开 \def

在 \write18 中展开 \def

我定义了以下命令:

\newcommand{\formatcommand}[1]{
    \def\temp{#1}
    \def\s{\ifx\temp\empty empty\else not empty\fi}
    echo "\s"
}

这可以正常工作:

\formatcommand{}
\formatcommand{ }

样本

然而,在里面使用上述命令时\write18

\immediate\write18{\formatcommand{}}

s\def似乎没有扩展,因为我得到的是\def is not an executable...,这意味着\write18将的主体发送\formatcommand{}到命令行而不进行扩展。如何解决这个问题?

平均能量损失

\documentclass[border=1cm]{standalone}


\begin{document}

\newcommand{\formatcommand}[1]{
    \def\temp{#1}
    \def\s{\ifx\temp\empty empty\else not empty\fi}
    echo "\s"
}

\formatcommand{}
\formatcommand{ }

\immediate\write18{\formatcommand{}}

\end{document}

答案1

当 TeX 写入命令内容时\write,它会像定义一样扩展所有材料\edef,即所有可扩展的命令都会被扩展,但不执行任何操作。宏定义(或其他赋值)不可扩展,因此\def当它们被写为 shell 命令时,s 会保留在输入流中。

解决方案是对空标记列表使用完全可扩展的测试,如以下\ifempty宏:

\makeatletter
\newcommand\ifempty[1]{%
    \if\relax\detokenize{#1}\relax
        \expandafter\@firstoftwo
    \else
        \expandafter\@secondoftwo
    \fi
}
\makeatother

\newcommand{\formatcommand}[1]{
    echo "\ifempty{#1}{empty}{not empty}"
}

答案2

一般来说,我推荐 siracusa 的解决方案,但是如果你使用 LuaTeX,如果你的问题无法以可扩展的方式编写,那么你可以使用另一个技巧:

LuaTeX 具有原语\immediateassignment\immediateassigned允许扩展\def的:

\documentclass[border=1cm]{standalone}


\begin{document}

\newcommand{\formatcommand}[1]{
    \immediateassignment\def\temp{#1}
    \immediateassignment\def\s{\ifx\temp\empty empty\else not empty\fi}
    echo "\s"
}

\formatcommand{}
\formatcommand{ }

\immediate\write255{\formatcommand{}}

\end{document}

(我用 替换了\write18\write255终端上显示命令,因为 shell-escape 在 LuaTeX 中的工作方式不同,因此执行命令需要进行更大的更改。)

使用\immediateassigned,您可以使块中的所有分配都可扩展:

\documentclass[border=1cm]{standalone}


\begin{document}

\newcommand{\formatcommand}[1]{
  \immediateassigned{%
    \def\temp{#1}
    \def\s{\ifx\temp\empty empty\else not empty\fi}
  }%
    echo "\s"
}

\formatcommand{}
\formatcommand{ }

\immediate\write255{\formatcommand{}}

\end{document}

相关内容