我正在为涉及 Unix 命令行的教程准备一些课程材料(PDF)。因为我追求自动化(有些人称之为懒惰),所以我编写了一个小包,允许我使用\write18
(with --shell-escape
)和verbatim
包来
- 运行命令(例如
ls
在命令处期间编辑我的.tex
文档并将它们排版在我的文档中, - 将结果重定向
stdout
到stderr
外部文件, - 在我的文档中输入那些外部文件进行排版
stdout
。stderr
.tex
但是,我的理解是每次调用都会\write18
打开和关闭自己的 shell 会话。这很不幸,因为它需要一些扭曲和代码重复。特别是,
- 在一个会话期间定义的所有 shell 变量在下一个会话中均不可用;
- 我必须
cd
在每个文件的开头都进入相同的目录\write18
,才能回到前一个文件末尾的相同目录\write18
。
请参阅下面我的玩具示例。
有什么方法可以在pdflatex
运行期间与 shell 交互,但又能以某种方式保持 shell 会话在一次\write18
调用和下一次调用之间保持打开状态?或者有没有更好的方法可以满足我的需求?
\documentclass{article}
\usepackage{lipsum}
\begin{document}
First, initialise the repository.
% pretend that the following is an environment that both
% - runs commands at the CL
% - typesets them in the .tex document
\immediate\write18{%
cd $HOME/Desktop;
mkdir myrepo;
cd myrepo;
git init;
}
Let's see what git has to say...
\immediate\write18{%
# I'm back in $HOME :(
# I have to cd to $HOME/Desktop/myrepo, here, but I'd like to avoid it...
cd $HOME/Desktop/myrepo;
git status
# ...
}
\end{document}
答案1
\documentclass{article}
\begin{document}
\immediate\write18{echo pwd > /tmp/zzpipe}
\texttt{\input{result.txt}}
\immediate\write18{echo cd > /tmp/zzpipe}
\immediate\write18{echo pwd > /tmp/zzpipe}
\texttt{\input{result.txt}}
\immediate\write18{echo 'FOO=wibble' > /tmp/zzpipe}
\immediate\write18{echo 'echo FOO is $FOO' > /tmp/zzpipe}
\texttt{\input{result.txt}}
\end{document}
a)设置一个“服务器”来接受命令,我只使用一个命名管道:
$ cd /tmp
$ mkfifo zzpipe
$ while true ; do eval `cat /tmp/zzpipe` >/tmp/result.txt ; done
然后运行上述 tex 文件(在/tmp
或排列result.txt
在其他地方写入)输出应如下所示。
这是在带有 cygwin bash 的 Windows 上,其他命令行将类似,但可能需要不同的引用约定。并且正如您所看到的,cd
和的设置FOO
在从一次写入到另一次写入时仍然存在。
答案2
我已经为...添加了基本的 bash 支持pythontex
,最终只用了不到 20 行代码。要使用此功能,您需要最新版本GitHubpythontex
。每当您需要执行新的 bash 代码时,您都需要使用标准的3 步编译(运行 LaTeX、运行 PythonTeX 脚本、运行 LateX)。当您没有需要执行的新代码时,您可以直接运行 LaTeX。由于这不使用\write18
,因此您不需要 shell-escape(代码执行由 PythonTeX 脚本处理)。
一切似乎都正常,但如果你发现任何错误,请告诉我。错误行号应与执行的代码行号正确同步。
这是一个示例文档,其输出如下所示。 \stdoutpythontex
默认情况下是逐字逐句的,因此不必像\printpythontex
(或等效的\stdoutpythontex
)那样指定格式。
\documentclass{article}
\usepackage[makestderr, usefamily=bash]{pythontex}
\setpythontexfv{numbers=left, firstnumber=last}
\begin{document}
A block of bash...
\begin{bashblock}
myvar="myvar's value"
echo $myvar
\end{bashblock}
...with output:
\printpythontex[verbatim]
Another block, accessing the previous variable...
\begin{bashblock}
echo "In another LaTeX environment later on..."
echo $myvar
\end{bashblock}
...with output:
\printpythontex[verbatim]
A block with an error.
\begin{bashblock}
echo "In another LaTeX environment later on..."
echo $myvar
lsERROR
\end{bashblock}
Stdout:
\printpythontex[verbatim]
Stderr:
\stderrpythontex
\end{document}