Erweitern Sie \def in \write18

Erweitern Sie \def in \write18

Ich habe folgenden Befehl definiert:

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

Das funktioniert einwandfrei:

\formatcommand{}
\formatcommand{ }

Probe

Wenn Sie jedoch den obigen Befehl innerhalb von verwenden \write18,

\immediate\write18{\formatcommand{}}

die \defs scheinen nicht erweitert zu werden, da ich bekomme \def is not an executable..., was bedeutet, dass \write18der Textkörper \formatcommand{}ohne Erweiterung an die Befehlszeile gesendet wurde. Wie kann das behoben werden?

MWE

\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}

Antwort1

Wenn TeX den Inhalt eines \writeBefehls schreibt, expandiert es das gesamte Material ähnlich wie bei einer \edefDefinition, d. h. alle erweiterbaren Befehle werden expandiert, es findet jedoch keine Ausführung statt. Makrodefinitionen (oder andere Zuweisungen) sind nicht erweiterbar, daher \defverbleiben die s im Eingabestrom, wenn sie als Shell-Befehle geschrieben werden.

Die Lösung besteht darin, einen vollständig erweiterbaren Test für eine leere Tokenliste zu verwenden, wie das folgende \ifemptyMakro:

\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}"
}

Antwort2

Im Allgemeinen empfehle ich die Lösung von siracusa, aber wenn Sie LuaTeX verwenden, gibt es einen anderen Trick, den Sie verwenden können, wenn Ihr Problem nicht erweiterbar geschrieben werden kann:

LuaTeX verfügt über Grundelemente \immediateassignment, \immediateassigneddie erweiterbare s ermöglichen \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}

(Ich habe es \write18durch ersetzt \write255, um den Befehl auf dem Terminal anzuzeigen, da Shell-Escape in LuaTeX anders funktioniert und die Ausführung des Befehls daher größere Änderungen erfordert hätte.)

Mit \immediateassignedkönnen Sie alle Zuweisungen in einem Block erweiterbar machen:

\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}

verwandte Informationen