3

I would like to use \immediate\write18 (encoded in the \OuputToFileA macro) to output a string containing a single quote. If I replace the single quote with another character, such as X

\StrSubstitute{\@CurrentString}{'}%
    {X}% <---- Replace the single quote
    [\@CurrentString]%

things work fine. But, I need the single quote in the output. Anything else I tried, such as escaping the single quote:

\StrSubstitute{\@CurrentString}{'}%
    {\@backslashchar\@backslashchar'}% <---- Attempt to escape the single quote
    [\@CurrentString]%

all result in an empty file.

Using \immediate\write (see \OuputToFileB macro) instead seems to work fine. How do I get this to work with \immediate\write18 instead?

Desired Output:

Afer pdflatex, the file foo.tex should contain

enter image description here

Notes:

  • Do not run this if you have foo.tex in the current directory as that will be overwritten.

Code:

\documentclass{article}
\usepackage{xparse}
\usepackage{xstring}

\immediate\write18{printf "\n" > foo.tex }% Initialize File

\makeatletter \NewDocumentCommand{\OuputToFileA}{% m% string to output }{% Output A to pdf: #1 \def@CurrentString{#1}% %% Using the first \StrSubstitute works. But, I don't want to replace the single quote %\StrSubstitute{@CurrentString}{'}% % {X}% <---- Replace the single quote % [@CurrentString]% \StrSubstitute{@CurrentString}{'}% {@backslashchar@backslashchar'}% <---- Attempt to escape the single quote [@CurrentString]% %% --------------------------------- \immediate\write18{printf 'string = "@CurrentString"' >> foo.tex }% \immediate\write18{printf "\n" >> foo.tex }% } \NewDocumentCommand{\OuputToFileB}{% m% string to output }{% Output B to pdf: #1 \def@CurrentString{#1}% No escaping required with \immediate %% --------------------------------- \newwrite\MyFile \immediate\openout\MyFile=foo.tex \immediate\write\MyFile{@CurrentString}% \immediate\closeout\MyFile% } \makeatother

\begin{document} \OuputToFileA{\detokenize{Einstein's Formula $E = mc^2$}}% %\OuputToFileB{\detokenize{Einstein's Formula $E = mc^2$}}% <-- Works! \end{document}

Peter Grill
  • 223,288
  • I think the proper escaping of the single-quote-in-a-double-quote-in-a-single-quote would be printf 'string = "Einstein'"'"'s Formula $E = mc^2$"\n' (see https://stackoverflow.com/a/1250279/6015190). The beautiful \StrSubstitute{\@CurrentString}{'}{'"'"'}[\@CurrentString] seems to work :) Or precede the whole single-quoted string with $ and use sane escape sequences: printf $'string = "Einstein\'s Formula $E = mc^2$"\n' (https://stackoverflow.com/a/16605140/6015190) – Phelype Oleinik Jan 05 '22 at 18:58
  • 1
    It may be in instruction for beginners (and more advanced users) how an ideal question may look like. :-) – Przemysław Scherwentke Jan 05 '22 at 19:00
  • Hm... But the last option on my comment is for bash and shell escaping seems to use sh, so that won't work. I'll stop commenting now :-) – Phelype Oleinik Jan 05 '22 at 19:04
  • @PhelypeOleinik: Replacing the single quote with {'"'"'} seems to work in the small test case. WIll test on my actual use case – Peter Grill Jan 05 '22 at 19:08
  • @PrzemysławScherwentke: Thanks for the complement. But, to be fair it is not always easy to do. I too have been told (at least once, if not more) by an extremely high rep user here that my question was not clear (not this specfic question) and what the desired ouptut is was not obvious -- and this was after I had been here several years. Furthermore, that was one of those times that I had tried hard to be clear as I realized that I was a bit confused. When you don't fully understand what the problem is, it is not easy to properly ask the question. – Peter Grill Jan 05 '22 at 21:35
  • This isn't really a TeX issue though. For debugging, make sure that • the write18 writes the correct thing to the shell (by changing the 18 to some real file), and that • the shell will run the command correctly with the desired result (just type into bash to try it out) ■ See also $ [\](https://tex.stackexchange.com/q/525424/250119) other – user202729 Jan 06 '22 at 08:33

1 Answers1

1

I've found a nice trick at https://stackoverflow.com/a/1250279/923955

Replace ' with '"'"'

In my opinion, the expl3 functions are much better than those of xstring. Besides, \sys_shell_now:n does no expansion to the input, without any other need. Alternating with \sys_shell_now:x is handier.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn % Initialize File \sys_shell_now:n {printf~"\n"~>~quotegrill.txt}

\NewDocumentCommand{\OuputToFile}{m} {% #1 is the string to write Output ~ to ~ pdf: ~ #1 \str_set:Nn \l_tmpa_str { #1 } \str_replace_all:Nnn \l_tmpa_str { ' } { '"'"' } \sys_shell_now:x {printf~'string~=~"\l_tmpa_str"'~>>~quotegrill.txt} \sys_shell_now:n {printf~"\n"~>>~quotegrill.txt} } \ExplSyntaxOff

\begin{document}

\OuputToFile{Einstein's Formula $E = mc^2$}

\end{document}

The output file will be


string = "Einstein's Formula $E = mc^2$"
egreg
  • 1,121,712