LaTeX 立即评估
我正在尝试在 LaTeX 中编写一个命令,该命令接受诸如 8:00A 之类的字符串并将其转换为分钟数,作为使用 TikZ 绘制课程表的脚本的一部分。然而,我遇到了一些问题 - 似乎 LaTeX 实际上并不评估命令的内容。
我的命令目前是:
\newcommand{\timetominutes}[1]{
\IfSubStr{#1}{P}{720}{0}+\IfSubStr{#1}{P}{\StrBetween{#1}{:}{P}}{\StrBetween{#1}{:}{A}}+60*\StrBefore{#1}{:}
}
如果您打印出其中的文本,它将正确计算从午夜开始的分钟数。但是,如果在另一个函数中使用,很明显它实际上并不运行任何这些命令 - 它只是返回包含这些命令的文本。因此,如果我写:
\myfunc{\timetominutes{8:00A}}
\myfunc
看到的不是像 0+00+60*8
这样有用的东西,而是看到 \IfSubStr{8:00A}{P} {720}{0}+\IfSubStr{8:00A}{P}{\StrBetween{8:00A}{:}{P}}{\StrBetween{8:00A}{:}{A}}+60* \StrBefore{8:00A}{:}
。这对我来说绝对没用,而且我找不到一种方法来强制 LaTeX 在主命令之前执行子命令。我认为有办法做到这一点,但 LaTeX 文档很少,我似乎找不到任何东西。
或者,如果有一种方法可以让 LaTeX 停止抱怨太多的 }
(当我有正确的数字时),那就可以了。
I'm trying to write a command in LaTeX that takes a string such as 8:00A and converts it into the number of minutes, as part of a script to draw a class schedule using TikZ. However, I'm running into some issues - it seems that LaTeX doesn't actually evaluate the contents of a command.
My command is currently:
\newcommand{\timetominutes}[1]{
\IfSubStr{#1}{P}{720}{0}+\IfSubStr{#1}{P}{\StrBetween{#1}{:}{P}}{\StrBetween{#1}{:}{A}}+60*\StrBefore{#1}{:}
}
If you print out the text from it, it will correctly calculate the number of minutes from midnight. However, if used inside another function, it becomes apparent that it doesn't actually run any of those commands - it merely returns text including those commands. So if I write:
\myfunc{\timetominutes{8:00A}}
Instead of \myfunc
seeing something useful like 0+00+60*8
, it sees \IfSubStr{8:00A}{P}{720}{0}+\IfSubStr{8:00A}{P}{\StrBetween{8:00A}{:}{P}}{\StrBetween{8:00A}{:}{A}}+60*\StrBefore{8:00A}{:}
. This is absolutely useless to me and I can't seen to find a way to force LaTeX to execute subcommands before the main one. I assume there's a way to do it, but LaTeX documentation is scarce and I can't seem to find anything.
Alternatively, if there's a way to get LaTeX to stop complaining about too many }
s (when I have the correct number), that could work.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不幸的是,没有。正如 xstring 包所述:
(xtring_doc_en.pdf 的第 3.2 节)。
如果您不熟悉这个“可扩展”概念,那么它在 TeX 中是一个相当棘手的主题。简而言之,不可扩展的东西不能被评估为参数。在大多数 TeX 变体中,任何在某处使用赋值的东西都保证不可扩展,但也存在其他不可扩展的触发器。对于不熟悉 TeX“嘴”(TeX 中处理扩展等事务的部分)内部工作原理的人来说,解决此类问题相当困难。
提示:如果 LaTeX 代码是由脚本生成的:使用脚本来转换时间表达式,因为在字符串操作方面几乎任何编程语言都比 TeX 更容易使用。 (或者任何其他与此相关的内容。)
xstring 包确实暗示了一种解决方法:您可以通过添加
[\variable]< 将大多数操作的结果存储在变量中。 /code> 到通话结束。这意味着您需要将
\timetominutes
重写为逐段构建结果的内容,然后将该结果存储在命令序列中以供稍后使用。用法:
注意
\expandafter
的使用,它告诉 TeX 在下一个命令序列之后对命令序列进行简单的一级扩展(求值)。如果您没有使用两个\expandafter
,您将得到\somevar
作为\myfunc
的参数,而不是48.
.(注意:前面是丑陋的 TeX 代码!)
\def
是与 LaTeX 的\newcommand
/\renewcommand
相对应的 TeX 原语。\edef
表示扩展\def
,它在将结果分配给命令序列之前评估定义。\numexpr
计算一个简单的数字表达式,例如由上述命令创建的 x + m + h * 60。还可以通过使用整数算术立即将结果计算为数字,而无需建立公式。但这会使代码更加偏离您的初衷。
可以通过 TeX 本身进行这些字符串操作,而无需使用 xstring 包(在这种特殊情况下甚至是可扩展的)。但这是相当低级的东西,如果您不是 TeX 专家,就很难重复这些内容。
Unfortunately, no. As the xstring package states:
(Section 3.2 of xtring_doc_en.pdf.)
This "expandable" concept, if you're not familiar with it, is quite a hairy subject in TeX. Simply put, something that is not expandable cannot be evaluated as an argument. Anything that uses an assignment somewhere is guaranteed not to be expandable in most TeX varieties, but other non-expandable triggers exist as well. The solution to such problems is rather difficult for anyone that's not familiar with the inner workings of TeX's "mouth" (the part of TeX that handles things like expansion).
Hint: If the LaTeX code is generated by a script: use the script to convert the time expressions, because just about any programming language is easier to use than TeX when it comes to string manipulation. (Or just about anything else for that matter.)
The xstring package does hint at a way out: You can store the result of most operations in a variable, by adding
[\variable]
to the end of the calls. This means you'd need to rewrite\timetominutes
to something that builds up the result piece by piece, and then store that result in a command sequence for use later on.Usage:
Note the use of
\expandafter
, which tells TeX to do a simple one-level expansion (evaluation) of a command sequence after the next. If you didn't use the two\expandafter
s, you'd get\somevar
as an argument to\myfunc
, not48
.(Caution: ugly TeX code ahead!)
\def
is the TeX primitive corresponding to LaTeX's\newcommand
/\renewcommand
.\edef
means Expanding\def
, which evaluates the definition before assigning the result to a command sequence.\numexpr
evaluates a simple number expression, like x + m + h * 60 created by the command above.It is also possible to calculate the result immediately as a number, without building up the formula, by using integer arithmetic. But that would make the code even more remote from your original intent.
It is possible to do these string manipulations through TeX itself, without using the
xstring
package (even expandible in this particular case). But that's pretty low level stuff, which cannot easily be repeated if you're not a TeX wizzard.我是 PerlTeX 的忠实粉丝,因为它可以在 LaTeX 中进行编程交互。使用 Perl 定义函数通常比在 TeX 中编程更容易,并且对于更多的编程操作,它可以更强大。 PerlTeX 为您提供了 perl 和 Latex 之间的双向通信,这意味着您可以将 Perl 代码片段嵌入到 LaTeX 源代码中,而不必编写创建整个源文件的脚本。
这是您想要的示例。使用
perltex --latex=pdflatex test.tex
进行编译,其中文件已保存为 test.tex,并且您可以省略可选的--latex=pdflatex
以生成 dvi。就扩展而言,如果您仍然遇到 \myfunc 问题,无论它是什么,您都可以将它或它的包装函数定义为 perltex 函数,或者使用提供的备用返回值。
I am a big fan of PerlTeX for programmatic interaction in LaTeX. Using Perl do define functions is often easier than programming in TeX and for more programmatic manipulation it can be far more powerful. PerlTeX gives you a two-way communication between perl and latex, meaning that you embed snippets of Perl code in your LaTeX source, rather than having to write a script that creates your entire source file.
Here is an example of what you wanted. Compile with
perltex --latex=pdflatex test.tex
where the file has been saved as test.tex and you may omit the optional--latex=pdflatex
for dvi generation.As far as expansion goes, if you still have problems with \myfunc, whatever it is, you can define it or a wrapper function for it as a perltex function or use the alternate returns provided.