从Latex代码文件中提取所有Latex命令

3

我正在尝试从tex文件中提取所有的latex命令。我需要使用Python来完成这个任务。我尝试使用Re模块将latex命令提取到一个列表中。

问题在于,这个列表不包含名称包含特殊字符的latex命令(例如\alpha*,\a',\#,\$,+,:,\;等)。它只包含由字母组成的latex命令。

我目前正在使用re.match Python命令:

    "I already know the starting index of '\' which is at self.i.
     The example Latex code string could be:
     \documentclass[envcountsame,envcountchap]{svmono}"

     match_text = re.match("[\w]+", search_string[self.i + 1:])

我可以提取'documentclass'。但是假设还有另一个命令,例如:

     "\abstract*[alpha]{beta}"
     "\${This is a latex document}"
     "\:" 

我应该如何从这些字符串中仅提取'abstract *','$',':'?
我是Python的新手,尝试了多种方法,但无法提取所有这些命令名称。如果有一个通用的Python Regex可以处理所有这些情况,那将会很有用。
注意:一本名为“The Not So Short introduction to LaTeX”的书定义了LaTeX命令的格式可以分为三种类型- 格式:
1. 以反斜杠\开头,后跟由字母组成的名称。命令名称以空格、数字或任何其他“非字母”字符终止。 2. 它们由反斜杠和正好一个非字母组成。 3. 许多命令存在“星号变量”,其中星号附加到命令名称。

1
使用 re.findall 时,似乎 r'\\([a-zA-Z]+)(\*)?' 是正确的正则表达式... - mgilson
对于包命令,@是一个字母,但这是一种情况,你不能在文件的更大上下文中捕获,即不能通过正则表达式合理地捕获。 - Ulrich Schwarz
\abstract*[alpha]{beta}实际上是带有三个参数的\abstract命令,分别是星号本身、可选的第二个参数和用大括号括起来的普通参数。因此,如果第一个参数是星号而不是其他字符,为什么要对其进行特殊处理呢? - Luis Colorado
2个回答

3
以下是您格式规范的确切翻译:

这是您格式规范的准确翻译:

\\(?:[^a-zA-Z]|[a-zA-Z]+)\*?

演示

  • 非字母: [^a-zA-Z]
  • 或字母: [a-zA-Z]+
  • 星号变体: \*?

如果您的格式描述准确,那么这应该可以做到。不幸的是,我不懂LaTeX,所以我不确定它是否完全正确。


从评论中的反馈来看,星号仅适用于字母命令,并且还可以有其他终止字符。最终正则表达式为:

\\(?:[^a-zA-Z]|[a-zA-Z]+[*=']?)

2
+1 我记得没有标准的单字符命令有星号变体,所以 \\(?:[^a-zA-Z]|[a-zA-Z]+\*?)(未经检查)也可以使用。还有其他各种情况(TeX 的分词器很特殊),但这应该可以获取大多数命令,在“正常”文档中误报较少。 - Norman Gray
谢谢。点赞了。这似乎在大多数情况下都有效,除了一个特定类型的情况。只有一种特定类型的情况没有被处理。我们有一些以字母开头并以不同于星号的非字母字符结尾的LaTeX命令。例如,“\a =”,“\a'”等。如果您能想到一个稍微修改过的正则表达式,那就太好了。 - shanu
1
The TeX book 中得知,某人在这里提到,多字母命令后面的空格必须包含在命令名称中(用于分隔目的,而不是匹配命令名称),因此,您的正则表达式在类似 \begin {} 的情况下会失败。更好的正则表达式应该是:\\([A-Za-z]+ *|.|\n)。但要小心像 Espa\~nol 这样的带重音符号的命令,因为它们会产生意想不到的效果。在 \LaTeX 中,星号命令被视为其第一个参数为星号。实际上,您为什么要消除 \LaTeX 的内容呢? - Luis Colorado
@LuisColorado:我正在做一个项目,需要解析一个文本文件,并获取其中所有LaTeX命令的结构。如果存在,我还会记录每个LaTeX命令所关联的方括号([ ])和花括号({ })参数。 - shanu
正如@ulrich Schwarz在顶部提到的那样,在包命令中,LaTeX将'@'视为一个字母。从语义上讲,我们知道它的作用,但我无法弄清楚如何使正则表达式理解这个事实。 - shanu
显示剩余4条评论

0

LaTeX是一个TeX宏包,因此,所有适用于TeX的内容也适用于LaTeX。

你提出的问题很难回答,因为TeX不是一种常规语言。如果你只想处理命令,你需要检查\\([A-Za-z]+ *|.|\n)正则表达式(参见demo),需要注意的是,在TeX中,有活动字符,即仅存在该字符就像执行了一个命令。如果你想处理命令参数,你需要检查各个命令的定义,因为TeX是一种波兰表示法(运算符或命令是前缀,具有可变数量的位置参数)语言。对于参数提取,TeX使用大括号匹配,这是上下文无关且不是正则的,因此你需要一个完整的解析器。

TeX允许您重新定义所有字符类,因此您可以将数字重新定义为字母并可用作命令名称(例如\a23是有效的命令名称)(这发生在包定义内部,其中@被用作字母,以便能够创建不可访问于用户但可用于包中的命令)

由于这个原因,消除LaTeX标记是一件困难的事情,您只能实现部分结果。有许多不同的问题需要解决(如何处理\include指令,如何处理参数中的有效文本,例如\chapter参数或\footnote,您想要包含索引等)

此外,您必须小心,因为如果尝试消除命令参数,则还会消除文本的一部分(例如\footnote中的文本,\abstract\title\chapter { ... } 等)。我不知道您实际想要获得的效果,因此在这方面我无法为您提供更多信息。


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