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

时间:2013-02-20 15:02:49

标签: python regex escaping html-parsing shopify

我正在尝试编写一个大型的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. 我的捕获组正在捕获整个原始源字符串,但是 我只需要在最后一个“/”

  3. 之后发生的事情

    ANSWER : Per Martijn Pieters有用的建议,我查了一下?正则表达式运算符,并提出了这个解决方案,完美解决了我的问题。另外,对于替换表达式,我将它封装在双引号中而不是单引号中,并且转义了双精度数,最终删除了不必要的反斜杠。谢谢你们!

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

2 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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 doc可能会有用;这一切都取决于你的HTML是多么美好和良好。