
我定義了以下命令:
\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 轉義在 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}