0

Note: \input is not expandable: Why is \input not expandable?
However, \@@input is.

The goal is to \@@input some text produced from a shell call, obtained via \sys_get_shell:nnN (for how, see egreg's answer on Write18: capturing shell (script) output as command/variable?).
For example, a shell call may produce output \A\B\C\D, which we want to insert into the input stream since the document defines these commands.
The result of \sys_get_shell:nnN is saved into a variable \result, so we want to pass that variable, expanded, to \@@input.
We can use \exp_args:Ne\@@input{\result} to expand \result before calling \@@input.

In order to \@@input something, you can either read from a file \@@input"my_file", or from the output of a shell command: \@@input"|my_shell_command_here".

In order to avoid writing to a temporary file, I'd like to use the shell | option.
Thus we could just |echo \result.
However, this wouldn't have the desired effect: in a shell command, \ is an escape character, so echo wouldn't print out exactly what we want, if it contains \ (or other shell-special other tokens like ().

My next idea was to protect every character passed to the shell with a \, which would seemingly have the desired result. If \result=\A\B\C\D, we pass \\\A\\\B\\\C\\\D to the shell:

$ echo \\\A\\\B\\\C\\\D
\A\B\C\D

To perform this mapping, we can use \tl_analysis_map_inline:nn (or \str_map_inline:nn?) to prepend every token with \:
\tl_analysis_map_inline:nn{\result}{\c_backslash_str#1}

For sake of example, let's assume that the shell output is:

hi
ho
\A\B\C\D
\A\B\C\D

so a full attempt looks like:

\documentclass[11pt]{article}

\begin{document}

\newcommand{\A}{myA}
\newcommand{\B}{myB}
\newcommand{\C}{myC}
\newcommand{\D}{myD}

\makeatletter
\newcommand{\expandableinput}[1]{ \@@input #1 }
\makeatother

\ExplSyntaxOn
\NewDocumentCommand{\inputfromecho} {m} {
   \expandableinput{"|echo~hi~&&~echo~ho~&&~echo~#1~&&~echo~#1"}
 }
 \NewDocumentCommand{\inputexpand} {m} {
 % Force expand #1 before calling \@@input
  \exp_args:Ne\inputfromecho{#1}
 }
\NewDocumentCommand{\sampleShellOutput} {} {
  \tl_analysis_map_inline:nn{ABCD}{\c_backslash_str##1}
 }
\NewDocumentCommand{\backslashProtectedShellOutput} {} {
  \exp_args:Ne\tl_analysis_map_inline:nn{\sampleShellOutput}{\c_backslash_str##1}
 }
\ExplSyntaxOff

Shell output:\\
\sampleShellOutput

Shell output as input:\\
\inputexpand{\backslashProtectedShellOutput}

\end{document}

However, this produces errors on the last 2 &s, and continuing, output:

  Shell output:
“A“B“C“D
  Protected shell output:
““A“B“C“D
  Shell output as input:
hi ho
  ““A“B“C“D echo ““A“B“C“D”

We also see from the console log that the shell command actually run was:
|echo hi && echo ho && echo
even though we expected to run:
|echo hi && echo ho && echo \\\A\\\B\\\C\\\D && echo \\\A\\\B\\\C\\\D

It seems like the \ print as ", and also match against " to finish the \@@input, cutting off the shell command in the middle.

Without " surrounding the shell command, \@@input seems to stop parsing the shell command at the first space.

Is there a simpler (or any successful) way to input a variable's fully-expanded contents as \input?

1
  • Sorry, but it's really unclear what's the aim.
    – egreg
    Dec 18, 2022 at 11:23

1 Answer 1

1

It's not really clear what the intention of the expansion control in the question is. I think there is confusion between expanding the argument of \input and expanding the returned tokens.

If you save the following as testcmd

echo hi
echo ho
echo '\A\B\C\D'
echo '\A\B\C\D'

and make it excutable;

$ chmod a+x ./testcmd 

(on windows you could make an equivalent testcmd.bat)

Then on the command line the command has the suggested output:

$ ./testcmd 
hi
ho
\A\B\C\D
\A\B\C\D

So to call that from latex use

pdflatex --shell-escape file

where file.tex is

\documentclass[11pt]{article}
\makeatletter
\def\shellcmd#1{\@@input"|#1" }
\makeatother

\begin{document}

\newcommand{\A}{myA}
\newcommand{\B}{myB}
\newcommand{\C}{myC}
\newcommand{\D}{myD}

\shellcmd{./testcmd}

\end{document}

Producing

enter image description here


The above answers the question in the title re interpretting the output of a shell call, but in comments you indicate an unrelated question, interpretting a tex token list as tex input, which I show below.


\documentclass{article}



\newcommand{\A}{myA}
\newcommand{\B}{myB}
\newcommand{\C}{myC}
\newcommand{\D}{myD}

\edef\var{hi
ho
\string\A\string\B\string\C\string\D
\string\A\string\B\string\C\string\D
}

\begin{document}

\verb|\var| character tokens: \texttt{\var}

Re-interpret \verb|\var| as \TeX: \scantokens\expandafter{\var}

\end{document}

enter image description here

4
  • The goal is to read an existing variable's value (after full expansion) as TeX input. For example, we have a variable whose value after full expansion is the string \A\B\C\D (note that all 8 characters, including the backslashes, are separate tokens with character code 11). We want to read these characters as LaTeX input, producing 4 tokens: \A \B \C \D. We don't know what the full expansion of the variable is going to be, so I'm looking for a general solution that expands some variable, then processes the resulting text as LaTeX input.
    – David Fink
    Dec 19, 2022 at 6:58
  • 1
    @DavidFink but that is completely unrelated to \{nput basically you are describing \scantokens. your existing question as far as can be understood is asking about using the | pipe syntax to input the output of a command available on the operating system command line Dec 19, 2022 at 8:16
  • @DavidFink I added a second answer Dec 19, 2022 at 9:52
  • awesome, \scantokens is exactly what I was looking for. The searchability of this question is tough - hopefully some keywords like "reinterpret as raw LaTeX input" will lead people to this page.
    – David Fink
    Dec 19, 2022 at 14:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .