我想解析一个LaTeX文档并用特殊命令标记它的一些术语。具体来说,我有一个术语列表,比如说:
Astah
UML
use case
...
我希望使用此自定义命令标记文本中第一次出现 Astah :\gloss{Astah}
。到目前为止,这是有效的(使用Python):
for g in glossary:
pattern = re.compile(r'(\b' + g + r'\b)', re.I | re.M)
text = pattern.sub(start + r'\1' + end, text, 1)
它工作正常。
但后来我发现了:
%
)\section{term}
或\paragraph{term}
)所以我尝试了这个:
for g in glossary:
pattern = re.compile(r'(^[^%]*(?!section{))(\b' + g + r'\b)', re.I | re.M)
text = pattern.sub(r'\1' + start + r'\2' + end, text, 1)
但它匹配注释中的术语,前面跟着其他字符,它也匹配标题内的术语。
我不理解正则表达式的“贪婪”吗?或者问题可能在其他地方?
举个例子,如果我有这个文字:
\section{Astah}
Astah is a UML diagramming tool... bla bla...
% use case:
A use case is a...
我想将其转换为:
\section{Astah}
\gloss{Astah} is a \gloss{UML} diagramming tool... bla bla...
% use case:
A \gloss{use case} is a...
答案 0 :(得分:1)
这里的诀窍是使用在行首开始匹配的正则表达式,因为这样我们就可以检查我们尝试匹配的单词是否有注释:
m
需要多行标记\1\\gloss{\2}
。这个正则表达式的出现将被替换为 let predicate = NSPredicate(format: "timeStamp == %@", parcoursTimeStamp as CVarArg)
let query = CKQuery(recordType: "ParcoursRecord", predicate: predicate)
privateDatabase.perform(query, inZoneWith: recordZone.zoneID, completionHandler: { (result, error) in
if let error = error {
print("Error querying for record: \(error.localizedDescription)")
} else {
print("Query result: \(result)")
}
})
。
答案 1 :(得分:0)
这是我的两分钱:
首先,我们需要使用regex module by Matthew Barnett。它带来了许多有趣的功能。在这种情况下,其功能之一可能很有用,添加了(*SKIP)
和(*FAIL)
。
- 新增(* PRUNE),(*跳过)和(*失败)(Hg issue 153)
(* PRUNE)会丢弃回溯信息。用于 原子组或环视,它不会影响封闭 图案。
(* SKIP)类似于(* PRUNE),除了它还设置在哪里 文本下一次匹配尝试将开始。在原子中使用时 组或环视,它不会影响封闭模式。
(* FAIL)导致立即回溯。 (* F)是允许的 缩写
因此,让我们构建模式并使用regex模块对其进行测试:
import regex
pattern = regex.compile(r'%.*(*SKIP)(*FAIL)|\\section{.*}(*SKIP)(*FAIL)|(Astah|UML|use case)')
s = """
\section{Astah}
Astah is a UML diagramming tool... bla bla...
% use case:
A use case is a...
"""
print regex.sub(pattern, r'\\gloss{\1}', s)
输出:
\section{Astah} \gloss{Astah} is a \gloss{UML} diagramming tool... bla bla... % use case: A \gloss{use case} is a...
这句话很好地说明了这一点:
诀窍是匹配我们不想要的各种情境,以便中和它们"。
在左侧,我们将编写我们不想要的背景。在右侧(最后一部分),我们捕捉到了我们真正想要的东西。因此,所有上下文都由一个交替符号|
分开,最后一个(我们想要的)被捕获。
因为在这种情况下,我们将进行更换,我们需要(* SKIP)(* FAIL)保持我们不想替换的匹配部分。
模式的含义:
%.*(*SKIP)(*FAIL)|\\section{.*}(*SKIP)(*FAIL)|(Astah|UML|use case)
%.*(*SKIP)(*FAIL) # Matches the pattern but skip and fail
| # or
\\section{.*}(*SKIP)(*FAIL) # Matches the pattern but skip and fail
| # or
(Astah|UML|use case) # Matches the pattern and capture it.
这个简单的技巧在RexEgg上更详细。
希望它有所帮助。