在Python中用正则表达式替换HTML脚本元素的源

1 投票
2 回答
1015 浏览
提问于 2025-04-17 16:30

我正在尝试写一个比较大的 Python 或 Bash 脚本,用来把我的 HTML/CSS 模型转换成 Shopify 主题。这个过程中的一个步骤是替换所有的脚本源地址。例如:

<script type="text/javascript" src="./js/jquery.bxslider.min.js"></script>

要变成

<script type="text/javascript" src="{{ 'jquery.bxslider.min.js' | asset_url }}"></script>

到目前为止,我已经做了这些:

import re
test = """
  <script type="text/javascript" src="./js/jquery-1.8.3.min.js"></script>
  <!--<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript"></script>-->
  <script type="text/javascript" src="./js/ie-amendments.js"></script>
  <script type="text/javascript" src="./js/jquery.bxslider.min.js"></script>
  <script type="text/javascript" src="./js/jquery.colorbox-min.js"></script>
  <script type="text/javascript" src="./js/main.js"></script>
"""
out = re.sub( 'src=\"(.+)\"', 'src="{{ \'\\1\' | asset_url }}"', test, flags=re.MULTILINE )
out

输出结果是

'\n  <script type="text/javascript" src="{{ \'./js/jquery-1.8.3.min.js\' | asset_url }}"></script>\n  <!--<script src="{{ \'http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript\' | asset_url }}"></script>-->\n  <script type="text/javascript" src="{{ \'./js/ie-amendments.js\' | asset_url }}"></script>\n  <script type="text/javascript" src="{{ \'./js/jquery.bxslider.min.js\' | asset_url }}"></script>\n  <script type="text/javascript" src="{{ \'./js/jquery.colorbox-min.js\' | asset_url }}"></script>\n  <script type="text/javascript" src="{{ \'./js/main.js\' | asset_url }}"></script>\n'

到现在为止,我遇到了两个问题:

  1. 我在正则表达式中用来转义单引号的反斜杠字符在输出中出现了。

  2. 我的捕获组捕获了整个原始源字符串,但我只需要最后一个“/”后面的部分。

回答:根据 Martijn Pieters 的建议,我查看了 ? 这个正则表达式操作符,找到了一个解决方案,完美地解决了我的问题。此外,在替换表达式中,我用双引号包裹,而不是单引号,并且对双引号进行了转义,这样就去掉了多余的反斜杠。谢谢大家!

re.sub( r'src=".+?([^/]+?\.js)"', "src=\"{{ '\\1' | asset_url }}\"", test, flags=re.MULTILINE )

2 个回答

1

如果不想惹恼某些人,你可以把它当作xml来处理。

txt = """<html>
<script type="text/javascript" src="./js/jquery.bxslider.min.js"></script>
<script type="text/javascript" src="./js/jquery.another.min.js"></script>
</html>
"""

import xml.etree.ElementTree as ET
import os
root = ET.fromstring(txt)

for e in root.findall('script'):
    e.attrib['src'] =  "{{ '%s' | assert_url }}" % os.path.basename(e.attrib['src'])

print ET.tostring(root)

这样做会得到:

<html>
<script src="{{ 'jquery.bxslider.min.js' | assert_url }}" type="text/javascript" />
<script src="{{ 'jquery.another.min.js' | assert_url }}" type="text/javascript" />
</html>

这个xml文档可能会在之后派上用场;这完全取决于你的HTML写得有多好,有多规范。

1

你的表达式运行得很好;Python只是给你显示了一个字符串字面量,如果你想把它当作Python字符串再使用,就需要对引号进行转义。

如果你打印这个值,就不会出现这样的转义:

>>> re.sub( 'src=\"(.+)\"', 'src="{{ \'\\1\' | asset_url }}"', test, flags=re.MULTILINE )
'\n  <script type="text/javascript" src="{{ \'./js/jquery-1.8.3.min.js\' | asset_url }}"></script>\n  <!--<script src="{{ \'http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript\' | asset_url }}"></script>-->\n  <script type="text/javascript" src="{{ \'./js/ie-amendments.js\' | asset_url }}"></script>\n  <script type="text/javascript" src="{{ \'./js/jquery.bxslider.min.js\' | asset_url }}"></script>\n  <script type="text/javascript" src="{{ \'./js/jquery.colorbox-min.js\' | asset_url }}"></script>\n  <script type="text/javascript" src="{{ \'./js/main.js\' | asset_url }}"></script>\n'
>>> print(re.sub( 'src=\"(.+)\"', 'src="{{ \'\\1\' | asset_url }}"', test, flags=re.MULTILINE ))

  <script type="text/javascript" src="{{ './js/jquery-1.8.3.min.js' | asset_url }}"></script>
  <!--<script src="{{ 'http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js" type="text/javascript' | asset_url }}"></script>-->
  <script type="text/javascript" src="{{ './js/ie-amendments.js' | asset_url }}"></script>
  <script type="text/javascript" src="{{ './js/jquery.bxslider.min.js' | asset_url }}"></script>
  <script type="text/javascript" src="{{ './js/jquery.colorbox-min.js' | asset_url }}"></script>
  <script type="text/javascript" src="{{ './js/main.js' | asset_url }}"></script>

你可以使用?来让+*?这些符号变成非贪婪的匹配,也就是说它们会尽量匹配最少的内容,而不是最多的内容。你还可以匹配任何不是引号的字符:

r'src="([^"]+)"'

这样可以更好地限制正则表达式的那部分;[^"]表示匹配任何不是双引号的字符。

在指定正则表达式模式时,通常建议使用Python的原始字符串字面量(r''),这样可以避免很多关于需要转义和不需要转义的麻烦。使用原始字符串字面量后,你的替换模式可以简化为:

r'src="{{ \'\1\' | asset_url }}"' 

最后一行是:

re.sub(r'src="([^"]+)"', r'src="{{ \'\1\' | asset_url }}"', test, flags=re.MULTILINE)

撰写回答