我的 HTML 文档中有一个字符串。
astring = "R=500 mm, φ=180°, Z=599 mm von TL Boden oben. Unterliegende Schale: Boden oben."
我想替换
astring
的子字符串来建立链接。为此,我有一个像这样的字典列表
lst = [{'id': 'coordinate_systems', 'linktext': 'TL Boden oben'},
{'id': 'PartID_1', 'linktext': 'Boden oben'}]
其中
linktext
字段是要在 astring
中找到的值。我想通过简单的替换来添加 href 标签,大致如下
astring.replace(linktext, '<a href="#{}">{}</a>'.format(_id, linktext))
通过迭代
lst
并在每行中进行替换。简单的实现是双循环,即根据 lst
的每个元素检查 HTML 文档的每一行并进行替换。
这会产生不正确的结果,例如首先替换子字符串“TL Boden oben”
'TL Boden oben' -> '<a href="#coordinate_systems">TL Boden oben</a>'
这是可以的,但是然后里面的“Boden oben”又被替换了
'Boden oben' -> '<a href="#coordinate_systems">TL <a href="#PartID_1">Boden oben</a></a>'
这已经不行了,我需要分别处理“TL Boden oben”和“Boden oben”:
"R=500 mm, φ=180°, Z=599 mm von <a href="#coordinate_systems">TL Boden oben</a>. Unterliegende Schale: <a href="#PartID_1">Boden oben</a>."
linktext
字段是用户定义的,所以是任意的。这些可能是不同的或重叠的,也就是说,我不能简单地以简单的方式进行替换,如前面所示。我没有先验知识如何linktext
字段重叠。
我找到并实现了一种解决方案,用于检查
astring
是否包含多个 linktext
。如果是这样,它只是将 astring
拆分为句子,并在句子级别进行替换;这是可以的,因为重叠的链接文本不太可能出现在同一个句子中(参见上面的示例)。
但这不是我想要的强大解决方案。
如何解决这个问题?
编辑:
通过 @Nick 的 answer,外部循环被消除,并且通过正则表达式替换完成替换。保留内部循环,因为并非所有出现的链接都将被替换,例如id 标签不应链接到其自身。
不应发生替换的行包含子字符串“nolink”。我的策略是循环各行,如果 'nolink' 不是行中的子字符串,则进行替换,否则将 'nolink' 替换为 ''。
部分原始内容(使用jinja2生成),替换前:
'<table class="table w-auto table-hover table-sm">\n'
'<thead>\n'
'<tr>\n'
'<th colspan="2" scope="col" id="PartID_1">Boden obennolink</th>\n'
'</tr>\n'
'</thead>\n'
'<tbody>\n'
'<tr>\n'
'<td>Halbkugelbodennolink</td>\n'
'<td>Position Z = 6000.0 mm. Bordhöhe 50.0 mm. Wanddicke s = 15 mm MW. Werkstoff 1.4541, Blech.</td>\n'
'</tr>\n'
'</tbody>\n'
'</table>\n'
'<table class="table w-auto table-hover table-sm">\n'
'<thead>\n'
'<tr>\n'
'<th colspan="2" scope="col" id="PartID_14">N02nolink</th>\n'
'</tr>\n'
'</thead>\n'
'<tbody>\n'
'<tr>\n'
'<td>Positionnolink</td>\n'
'<td>R=500 mm, φ=180°, Z=599 mm von TL Boden oben. Unterliegende Schale: Boden oben. Ausrichtung: normal.</td>\n'
'</tr>\n'
'<tr>\n'
'<td>Zargenolink</td>\n'
'<td>168.3 mm x 5.60 mm NW (5.20 mm MW). Werkstoff 1.4571, Blech.</td>\n'
'</tr>\n'
'</tbody>\n'
'</table>\n'
您可以同时使用正则表达式替换all链接模式来解决此问题,因为这不会替换之前替换的文本。关键是要确保
linktext
值按长度降序排序;这样TL Boden oben
就不会被错误地替换为Boden oben
的链接。为了简化替换,我们制作了从 linktext
到生成的链接文本的映射。例如:
astring = "R=500 mm, φ=180°, Z=599 mm von TL Boden oben. Unterliegende Schale: Boden oben."
lst = [{'id': 'coordinate_systems', 'linktext': 'TL Boden oben'},
{'id': 'PartID_1', 'linktext': 'Boden oben'}]
links = { l['linktext'] : f'''<a href="#{l['id']}">{l['linktext']}</a>''' for l in lst }
# {
# 'TL Boden oben': '<a href="#coordinate_systems">TL Boden oben</a>',
# 'Boden oben': '<a href="#PartID_1">Boden oben</a>'
# }
pattern = re.compile('|'.join(sorted(links.keys(), key=len, reverse=True)))
# re.compile('TL Boden oben|Boden oben')
out = pattern.sub(lambda m:links[m[0]], astring)
输出:
'R=500 mm, φ=180°, Z=599 mm von <a href="#coordinate_systems">TL Boden oben</a>. Unterliegende Schale: <a href="#PartID_1">Boden oben</a>.'