如何从LaTeX执行shell脚本?

65

我正在尝试在LaTeX中做以下操作:

\documentclass{article}
\begin{document}
\execute{/usr/local/bin/my-shell-script.sh}
\end{document}

这个想法是在.tex文档处理的那一刻执行/usr/local/bin/my-shell-script.sh脚本,并将其输出注入LaTeX流中。这真的可能吗?

PS. 通过我制作的包iexec,这是可能的


1
请参见 http://stackoverflow.com/questions/2671079/how-can-i-save-shell-output-to-a-variable-in-latex - Charles Stewart
18
有趣的是,这个帖子被标记为“离题”。 - Orion
1
也许你可以将你的可能解决方案与iexec包一起移动到一个新的答案中,并附上一个简短的示例?这样做可能会比将其隐藏在后记中更容易被大家看到。 - samcarter_is_at_topanswers.xyz
@samcarter_is_at_topanswers.xyz 这个问题已经“关闭”,我无法在其上发布新的回答 :( - yegor256
@yegor256 是的,我注意到了当我试图将一个新问题关闭为重复时 :( 我已经投票重新打开,但还没有结果 :( - samcarter_is_at_topanswers.xyz
6个回答

57
我会按照以下方式进行操作(部分来源于Roman的建议):将您的LaTeX文件设置为:
\documentclass{article}
\begin{document}
\input{scriptoutput.tex}
\end{document}

使用以下命令生成名为scriptoutput.tex的文件:

/usr/local/bin/my-shell-script.sh > scriptoutput.tex

你可以将此内容编码到 makefile 中,以使其在必要时自动运行。或者,您可以使用 TeX 的 \write18 命令。
\documentclass{article}
\immediate\write18{/usr/local/bin/my-shell-script.sh > scriptoutput.tex}
\begin{document}
\input{scriptoutput.tex}
\end{document}

我认为这样做可以在每次编译文档时自动运行shell脚本。 \immediate 是必需的,以确保当LaTeX遇到该命令时立即运行脚本,而不是等到输出页面被写入才运行(更多关于shipout程序的信息,请参见这个问题)。


你的解决方案肯定比我的更简洁。如果你有很多替换的话,我的解决方案会更方便。 - Roman Cheplyaka
1
@DavidZ 你可能想使用\immediate\write18而不是裸的\write18。没有\immediate,写操作可能会被缓冲,直到下一次调用shipout例程。 - Henri Menke

45

正如David指出的那样,您可以使用\write18来调用外部程序,然后\input结果输出文件。但是,您可能需要使用\immediate\write18确保在调用\input之前执行脚本。

或者,如果您使用更新版本的pdf(la)tex(我认为在1.40之后),您可以通过使用管道输入命令直接将输出导入文档:

\documentclass{article}
\begin{document}
\input{|"/usr/local/bin/my-shell-script.sh"}
\end{document}

对于任何一种方法,您都需要启用外部程序调用。对于TeXlive发行版,您需要使用-shell-escape选项调用latex,而对于MikTeX,我认为选项是-enable-write18


如果您在Windows上使用TeXworks,您可能想要传递--tex-option=--shell-escape而不是仅传递--shell-escape。否则,您将收到一个晦涩的错误消息:抱歉,但“MiKTeX编译器驱动程序”未成功。 - GuiTeK
1
\input 管道甚至可以与 shell 管道一起使用。例如,\input{|"jq -r .my_key my_file.json | wc"} 可以工作! - rickhg12hs

11

你可以在TeX中完成这个任务。这篇文章(PDF)会向你展示如何在TeX中编写和执行病毒。同样的原理也适用于执行shell脚本。然而,在我看来,编写一个Makefile更加实用,它可以在你运行LaTeX之前运行并插入结果。


6
在Ubuntu 11.10 GNU/Linux上
pdflatex --enable-pipes --shell-escape mytexfile

使用

%...
[This section currently is 
\input{|"wc kmb-box.tex| tr -s ' ' | cut -d' ' -f 4"}
% 2000 characters are allowed here

\input{kmb-box}

%...

这个功能非常好用。也就是说,它使用wordcount(wc)来报告文件kmb-box.tex中有多少个字符,该文件是文档的一部分(包含在内)。

顺便说一句,如果你想要的是单词而不是字符,只需更改“-f 4”中的数字即可。


当我将命令切换为“ls”时,我会收到错误。命令输出中的换行符有问题吗? - Alec Jacobson

3

除非在运行LaTeX时必须运行脚本,否则我建议只使用make来运行LaTeX和您的脚本。

我使用这种方法为文章添加字数统计,并包括参考文献的统计数据。

让您的脚本生成一个.tex文件,并将其包含在您的LaTeX源文件中。

以下是我的一个Makefile的片段:

TEX =   /usr/texbin/pdflatex
PREVIEW = /usr/bin/open

REPORT  =   SimMon
REPORT_MASTER = $(REPORT).tex

TEX_OPTIONS = -halt-on-error

SimMon:  $(REPORT_MASTER) countRefferedPages
    $(TEX) $(TEX_OPTIONS) $(REPORT_MASTER)
    @$(PREVIEW) $(REPORT).pdf

countRefferedPages: BibTeXPageCount
    cat *.tex | support/BPC/build/Debug/BPC Castle.bib > litteraturTotal.tex

1

这是我使用自己的iexec软件包的方法:

\documentclass{article}
\usepackage{iexec}
\begin{document}
\iexec{/usr/local/bin/my-shell-script.sh}
\end{document}

当不需要输出时,我可以只做这个:
\iexec[quiet]{/usr/local/bin/my-shell-script.sh}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接