我的代码/想法来自两个主题: 从另一个文件输入参数 文件内容:选择要显示的组的行
文件parameters.tex
:
\documentclass{article}
\usepackage[utf8]{vietnam}
\usepackage{verbatim}
\usepackage{comment}
\usepackage{filecontents}
\begin{filecontents*}{products.tex}
No|Time|Velocity
11|"5s"|"3m/s"
22|"10s"|"7m/s"
33|"20s"|"14m/s"
\end{filecontents*}
\usepackage{datatool}
\DTLsetseparator{|}
\DTLloaddb[autokeys=false]{products}{products.tex}
\newcommand{\printtype}[1]{%
\par
\DTLforeach*
[\DTLiseq{\No}{#1}]% Condition
{products}% Database
{\No=No,\Time=Time,\Velocity=Velocity}{%
time = \Time \par max\_velocity = \Velocity
}%
}
\begin{document}
\printtype{11}
\end{document}
编译此parameters.tex
文件将生成一个 DVI 或 PDF 文件,其中包含:
time = 5s
max_velocity = 3m/s
但我想从以下main.tex
文件中解析此输出,并能够使用其中的“时间”和“max_velocity”值main.tex
。
文件main.tex
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\ior_new:N \ar_param_file
\seq_new:N \g_ar_param_seq
\cs_new:Nn \ar_read_by_line:n {%
\seq_gput_right:Nn \g_ar_param_seq {#1}% Appending the current line to the global sequence buffer
}
\NewDocumentCommand{\paraminput}{O{}m}{%
\seq_gclear:N \g_ar_param_seq% Clearing the sequence
\ior_open:Nn \ar_param_file {#2} % Open the input file
\ior_map_inline:Nn \ar_param_file {\ar_read_by_line:n{##1}}% Reading line by line
\ior_close:N \ar_param_file% Closing the line
\seq_map_inline:Nn \g_ar_param_seq {% Traversing through the line
\seq_set_split:Nnn \l_tmpa_seq {=} {##1} % Splitting each line into 'key=value' pairs
\seq_if_in:NxT \l_tmpa_seq {#1} {\seq_item:Nn \l_tmpa_seq {2}\seq_map_break:}% Checking if `#1` is in the sequence and display it with \seq_item:Nn..., then break the mapping loop.
}
}
\ExplSyntaxOff
\begin{document}
The trajectory travels the distance of
\paraminput[time]{parameters.tex}. % <==========================
The maximum observed velocity is \paraminput[max_velocity]{parameters.tex}. ...
\end{document}
我使用 LaTeX、texmarker?如何使用parameters.tex
from within输出的参数main.tex
?我需要 R 还是只需要 LaTeX?
答案1
显然,您确实想以文本格式写入中间文件。这里有一种方法可以做到这一点,使用\write
(请注意,输出文件名为parameters.txt
)。
内容parameters.tex
:
\RequirePackage{filecontents}
\begin{filecontents*}{products.tex}
No|Time|Velocity
11|"5s"|"3m/s"
22|"10s"|"7m/s"
33|"20s"|"14m/s"
\end{filecontents*}
\documentclass{article}
\usepackage{datatool}
\DTLsetseparator{|}
\DTLloaddb[autokeys=false]{products}{products.tex}
\newwrite\myOutput
\immediate\openout\myOutput=parameters.txt
\AtEndDocument{\immediate\closeout\myOutput}
\newcommand{\printForNumber}[1]{%
\DTLforeach*%
[\DTLiseq{\No}{#1}]% Condition
{products}% Database
{\No=No,\Time=Time,\Velocity=Velocity}{%
\immediate\write\myOutput{time=\Time}%
\immediate\write\myOutput{max_velocity=\Velocity}%
}%
}
\begin{document}
\printForNumber{11}
\end{document}
这将生成一个名为 的文件parameters.txt
,其中包含以下行:
time=5s
max_velocity=3m/s
您的main.tex
代码可以正常工作,但前提是您在两次调用中替换parameters.tex
了。但是,您的代码中用于选择包含所需参数名称的第一行(此处:或)的方式可以稍微改进一下——您可以在下面找到我的建议。在我看来,主要问题是您对给定参数名称的相等性测试适用于parameters.txt
\paraminput[〈param name〉]{〈file〉}
main.tex
time
max_velocity
两个都等号两边:参数名称(可以)以及参数值(不太好……)。
我还尝试按照 LaTeX3 推荐的代码风格来安排代码(参见LaTeX3 编程语言和LaTeX3 风格指南在这一页)。我将命令的整个逻辑移到\paraminput
了一个新的\ar_find_data_in_file:nn
受保护命令中,这样文档级命令 ( \paraminput
) 只需使用其两个参数即可调用\ar_find_data_in_file:nn
。 的可选参数的空默认值很奇怪,但我想你会用或类似的东西\paraminput
替换它。因此,我没有将此可选参数更改为强制参数。所以,这是修改后的文件:time
max_velocity
main.tex
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\ior_new:N \g_ar_param_file
\seq_new:N \g_ar_param_seq
\cs_new_protected:Nn \__ar_read_by_line:n
{
% Append the current line to the global sequence \g_ar_param_seq
\seq_gput_right:Nn \g_ar_param_seq {#1}
}
% #1: parameter name such as 'time' or 'max_velocity'
% #2: input file
\cs_new_protected:Npn \ar_find_data_in_file:nn #1#2
{
\seq_gclear:N \g_ar_param_seq % Clear the sequence
\ior_open:Nn \g_ar_param_file {#2} % Open the input file #2
% Read it line by line into sequence \g_ar_param_seq
\ior_map_inline:Nn \g_ar_param_file { \__ar_read_by_line:n {##1} }
\ior_close:N \g_ar_param_file % Close the file
\seq_map_inline:Nn \g_ar_param_seq % For each line
{ % Split it around the '=' sign
\seq_set_split:Nnn \l_tmpa_seq {=} {##1}
% Get the parameter name
\seq_get_left:NN \l_tmpa_seq \l_tmpa_tl
% If #1 is the name of the parameter for the current line, leave it in
% the TeX input stream and break out of the mapping loop.
\str_if_eq:VnT \l_tmpa_tl {#1}
{
\seq_map_break:n % Get the parameter value and break
{ \seq_item:Nn \l_tmpa_seq { 2 } }
}
}
}
\NewDocumentCommand \paraminput { O{} m }
{
\ar_find_data_in_file:nn {#1} {#2}
}
\ExplSyntaxOff
\begin{document}
The trajectory took \paraminput[time]{parameters.txt}.
The maximum observed velocity was \paraminput[max_velocity]{parameters.txt}.
\end{document}