
Eu defini o seguinte comando:
\newcommand{\formatcommand}[1]{
\def\temp{#1}
\def\s{\ifx\temp\empty empty\else not empty\fi}
echo "\s"
}
Isso funciona corretamente:
\formatcommand{}
\formatcommand{ }
No entanto, ao usar o comando acima dentro \write18
,
\immediate\write18{\formatcommand{}}
o \def
s parece não estar se expandindo, já que estou recebendo \def is not an executable...
, o que significa que \write18
enviou o corpo \formatcommand{}
sem expandi-lo para a linha de comando. Como isso pode ser consertado?
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}
Responder1
Quando o TeX escreve o conteúdo de um \write
comando, ele expande todo o material de forma semelhante ao que acontece em uma \edef
definição, ou seja, todos os comandos expansíveis são expandidos, mas nenhuma execução acontece. As definições de macro (ou outras atribuições) não são expansíveis, portanto, os \def
s permanecem no fluxo de entrada quando são escritos como comandos shell.
A solução é usar um teste totalmente expansível para uma lista de tokens vazia, como a seguinte \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}"
}
Responder2
Geralmente eu recomendo a solução siracusa'a, mas se você usar LuaTeX, há outro truque que você pode usar se o seu problema não puder ser escrito de maneira expansível:
LuaTeX possui primitivas \immediateassignment
e \immediateassigned
que permitem \def
s expansíveis:
\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}
(Substituí \write18
por \write255
para mostrar o comando no terminal porque shell-escape funciona de maneira diferente no LuaTeX, então a execução do comando precisaria de mudanças maiores.)
Usando \immediateassigned
, você pode tornar todas as atribuições em um bloco expansíveis:
\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}