
He definido el siguiente comando:
\newcommand{\formatcommand}[1]{
\def\temp{#1}
\def\s{\ifx\temp\empty empty\else not empty\fi}
echo "\s"
}
Esto funciona correctamente:
\formatcommand{}
\formatcommand{ }
Sin embargo, cuando se utiliza el comando anterior en el interior \write18
,
\immediate\write18{\formatcommand{}}
los \def
s parecen no expandirse, ya que estoy obteniendo \def is not an executable...
, lo que significa que \write18
envió el cuerpo de \formatcommand{}
sin expandirlo a la línea de comando. ¿Cómo se puede arreglar esto?
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}
Respuesta1
Cuando TeX escribe el contenido de un \write
comando, expande todo el material de manera similar a lo que sucede en una \edef
definición, es decir, todos los comandos expandibles se expanden pero no ocurre ninguna ejecución. Las definiciones de macros (u otras asignaciones) no se pueden expandir, por lo que los \def
mensajes de correo electrónico permanecen en el flujo de entrada cuando se escriben como comandos de shell.
La solución es utilizar una prueba completamente expandible para una lista de tokens vacía, como la siguiente \ifempty
macro:
\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}"
}
Respuesta2
Generalmente recomiendo la solución siracusa, pero si usas LuaTeX hay otro truco que puedes usar si tu problema no se puede escribir de manera expandible:
LuaTeX tiene primitivas \immediateassignment
y \immediateassigned
que permiten \def
s expandibles:
\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}
(Lo reemplacé \write18
con \write255
para mostrar el comando en la terminal porque shell-escape funciona de manera diferente en LuaTeX, por lo que ejecutar el comando habría necesitado cambios mayores).
Usando \immediateassigned
, puedes hacer que todas las asignaciones en un bloque sean expandibles:
\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}