我如何 \write18 一个 koma 变量?

我如何 \write18 一个 koma 变量?

我正在尝试对依赖于 TeX 文件内部设置的某些数据进行 shell 处理。为此,我想要\immediate\write18一个依赖于 的命令\usekomavar,但pdflatex会抱怨额外的}

口粮:

\documentclass{scrlttr2}

\newcommand\x[1]{hello #1} 

\begin{document}

\begin{letter}{Person} % <- toname should be 'Person'
\opening{Opening}

\immediate\write18{echo 'none' > \jobname-none.txt} % fine
\immediate\write18{echo '\x{world}' > \jobname-x.txt} % fine
\immediate\write18{echo '\usekomavar{toname}' > \jobname-toname.txt} % error

\closing{Closing}
\end{letter}

\end{document}

具体来说,它告诉我:

$ pdflatex --shell-escape mre.tex
...snip...
! Argument of \reserved@a has an extra }.
<inserted text> 
                \par 
l.12 ...usekomavar{toname}' > \jobname-toname.txt}

重要的是,我不想逃避命令。文件内容应该是Person,而不是\usekomavar{toname}在运行命令之后。

答案1

KoMa 变量基本上是以名称 保存的宏\scr@VARNAME@var\usekomavar是一个强大的宏,用于检查变量是否已定义以及后面是否有星号,如果是,则执行其他操作。 如果您准备放弃这些检查,则只需使用\csname scr@VARNAME@var\endcsname。 最坏的情况:KoMa 变量未定义,并且什么也没发生。

\immediate\write18{echo '\csname scr@toname@var\endcsname' > \jobname-toname.txt}

答案2

也可以使用可选参数\usekomavar。因此我必须定义一个新的宏,它将文件的内容作为其最后一个参数。

\newcommand\writetofile[2]{% \writetofile{<file>}{<content>}
  \immediate\write18{echo '#2' > #1}%
}

然后就可以使用

\usekomavar[\writetofile{\jobname-toname.txt}]{toname}

以获得期望的结果。

例子:

\documentclass{scrlttr2}
\newcommand\x[1]{hello #1} 

\newcommand\writetofile[2]{% \writetofile{<file>}{<content>}
  \immediate\write18{echo '#2' > #1}%
}

\begin{document}
\begin{letter}{Person} % <- toname should be 'Person'
\opening{Opening}

\immediate\write18{echo 'none' > \jobname-none.txt}% fine
\immediate\write18{echo '\x{world}' > \jobname-x.txt}% fine
\usekomavar[\writetofile{\jobname-toname.txt}]{toname}%

\closing{Closing}
\end{letter}
\end{document}

或者

\documentclass{scrlttr2}
\newcommand\x[1]{hello #1} 

\newcommand\writetofile[2]{% writetofile{<file>}{<content>}
  \immediate\write18{echo '#2' > #1}%
}

\newcommand\writekomavar[2]{% \writekomavar{<file>}{<variable>}
  \usekomavar[\writetofile{#1}]{#2}%
}

\begin{document}
\begin{letter}{Person} % <- toname should be 'Person'
\opening{Opening}

\immediate\write18{echo 'none' > \jobname-none.txt}% fine
\immediate\write18{echo '\x{world}' > \jobname-x.txt}% fine
\writekomavar{\jobname-toname.txt}{toname}%

\closing{Closing}
\end{letter}
\end{document}

答案3

正如 Ulrike 所说,\usekomavar不可扩展,但可以轻松创建功能等效的可扩展版本。不可扩展意味着该命令在其处理过程中执行赋值,因此在 或 内使用时会失败\edef\write下面的命令仅使用可扩展命令,因此在 内\write它会扩展到变量的值。

\documentclass{scrlttr2}

\newcommand\x[1]{hello #1}

\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand\xusekomavar{sO{\use:n}m}
  {
    \IfBooleanTF{#1}%
      { \__bitmask_usekomathing:nnn {name} }
      { \__bitmask_usekomathing:nnn {var} }
          {#2} {#3}
  }
\cs_new:Npn \__bitmask_usekomathing:nnn #1 #2 #3
  {
    \cs_if_exist:cTF { scr@#3@var }
      { \exp_args:Nnc \use:n {#2} { scr@#3@#1 } }
      { \msg_expandable_error:nnn { bitmask } { undefined-komavar } {#3} }
  }
\msg_new:nnn { bitmask } { undefined-komavar }
  { KOMA-Script~variable~`#1'~not~defined. }
\ExplSyntaxOff

\begin{document}

\begin{letter}{Person} % <- toname should be 'Person'
\opening{Opening}

\immediate\write18{echo 'none' > \jobname-none.txt} % fine
\immediate\write18{echo '\x{world}' > \jobname-x.txt} % fine
\immediate\write18{echo '\xusekomavar{toname}' > \jobname-toname.txt} % error

\closing{Closing}
\end{letter}

\end{document}

相关内容