在Python中用正则表达式替换HTML脚本元素的源
我正在尝试写一个比较大的 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'
到现在为止,我遇到了两个问题:
我在正则表达式中用来转义单引号的反斜杠字符在输出中出现了。
我的捕获组捕获了整个原始源字符串,但我只需要最后一个“/”后面的部分。
回答:根据 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)