【问题标题】:Between double curly braces: replace particular text双花括号之间:替换特定文本
【发布时间】:2015-11-09 10:28:24
【问题描述】:

我有一个字符串(Python 2.7.3),它在 Django 中呈现为模板,但我认为这不是 Django 特有的。该字符串来自 docx 文件中的 document.xml 文件。我正在提取文档 xml 渲染它并将其放回 docx 中以获取一些简单的邮件合并类型的东西。

除了我可以使用的模板标签的明显限制之外,还有一个问题是,如果您在 Word 中编辑文本,Word 喜欢放入一大堆 xml。

为了我的需要,如果可以,我会成功

  1. 在双花括号之间查找所有出现的" 并替换为引号"

我想将" 替换为",如下所示:

word_docxml = 'some text here {{form.letterdate|date:"Y-m-d"}} and more text'

我正在阅读这些:

但无法将它们组合在一起。

  1. 如何删除/剥离内部的所有内容,包括 {{ }} 之间的 < >,如下所示:

    <w:rPr>
      <w:rFonts w:eastAsia="Times New Roman" w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/>
      <w:color w:val="00000A"/>
      <w:sz w:val="22"/>
      <w:szCs w:val="22"/>
      <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/>
    </w:rPr>
    <w:t>{{form.</w:t>undefined</w:r>undefined<w:r>
    <w:rPr>
      <w:rFonts w:eastAsia="Times New Roman" w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/>
      <w:b w:val="false"/>
      <w:bCs w:val="false"/>
      <w:color w:val="00000A"/>
      <w:sz w:val="22"/>
      <w:szCs w:val="22"/>
      <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/>
    </w:rPr>
    <w:t>L</w:t>undefined</w:r>undefined<w:r>
    <w:rPr>
      <w:rFonts w:eastAsia="Times New Roman" w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/>
      <w:color w:val="00000A"/>
      <w:sz w:val="22"/>
      <w:szCs w:val="22"/>
      <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/>
    </w:rPr>
    <w:t>etterDate.value|date:"Y-m-d"}}</w:t>undefined</w:r>
    

这将导致以下结果(抱歉,我似乎无法突出显示感兴趣的领域):

<w:rPr>
  <w:rFonts w:eastAsia="Times New Roman" w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/>
  <w:color w:val="00000A"/>
  <w:sz w:val="22"/>
  <w:szCs w:val="22"/>
  <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/>
</w:rPr>
<w:t>{{form.LetterDate.value|date:"Y-m-d"}}</w:t>undefined</w:r>

如何处理这个问题?正则表达式是要走的路吗?如果是这样,如何将命令放在一起?

这不是 Between double curly braces: replace particular text 的重复,因为它没有提到处理搜索范围的开始和结束的双花括号(这是我真正的问题,我已经阅读了许多示例并且无法获得替换的模式格式正确)。另一篇文章是关于在 XHTML 中解析 html 实体的子集;我的帖子中不需要、提到或质疑 XHTML 解析。此处的这篇文章询问如何删除和/或替换其他两个已知开始/结束模式之间的重复模式。我提供了一个简短的背景,两个从简单到复杂的具体例子,希望学习如何完成我目前的任务——我最大的希望是解释 A 部分并将该方法自己应用到 B 部分。我得到了聪明的讨论和超级回复来自社区的乐于助人的成员。我的帖子根本不涉及 HTML,因为我在 Django 中呈现的模板被添加回 docx 存档并保存到文件存储中。它不是重复的(无论如何标记的重复)。

【问题讨论】:

  • re.sub('\&amp;quot', '\"', s)
  • 问题与什么重复?问题是要替换大括号之间的特定内容,并且除了作为模板语言的一部分之外与 HTML 无关。如果作者有 1000 个这样的文件并且需要对其进行整理,为什么不适合用解决方案来回答这个问题?只是把那个帖子扔了,不管它多么有趣,都不是正确的!给我看这篇文章的任何部分,甚至提到除了 cmets 之外的 HTML。
  • @melwil 我同意 melwil。我们有句话说,射蚊子不需要大象枪。使用工具箱中最简单的工具解决问题。 Html 解析器并不太难使用,但我确定有一些必要的牦牛剃须比较来启动一个充分解决问题的正则表达式,并且可以在任何开箱即用的语言。不要用大象霰弹枪来解决这个简单的问题,如果你已经掌握了正则表达式或者当然想要改进。
  • “他们”删除了重复的状态? Stackoverlfow 的胜利!,太棒了 :)
  • 即使在我的旗帜被宣布为“没有帮助”之后!我已经放弃了,但我想有人终于看到了原因。无论如何,没有办法用 HTML 解析器解决这个问题,它不是 HTML。 :p

标签: python regex django python-2.7


【解决方案1】:

是的,正则表达式非常适合这个!

a) 使用这个:

 re.sub(r"(\{\{[^}]+}\})", lambda m: re.sub("&quot;", '"', m.group(1)), word_docxml)

结果:

>>> word_docxml = 'some text here {{form.letterdate|date:&quot;Y-m-d&quot;}} and &quot; more text'
>>> re.sub(r"(\{\{[^}]+}\})", lambda m: re.sub("&quot;", '"', m.group(1)), word_docxml)
'some text here {{form.letterdate|date:"Y-m-d"}} and &quot; more text'

b) 更多相同,只是匹配大括号内的不同内容;

re.sub(r"(\{\{[^}]+}\})", lambda m: re.sub("<[^>]+>", "", m.group(1)), s)

结果:

>>> s = """<w:rPr><w:rFonts w:eastAsia="Times New Roman" w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/><w:color w:val="00000A"/><w:sz w:val="22"/><w:szCs w:val="22"/><w:US" w:eastAsia="en-US" w:bidi="ar-SA"/></w:rPr><w:t>{{form.</w:t></w:r><w:r><w:rPr><w:rFonts w:eastAsia="Times New Roman" w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/><e"/><w:bCs w:val="false"/><w:color w:val="00000A"/><w:sz w:val="22"/><w:szCs w:val="22"/><w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/></w:rPr><w:t>L</w:t></w<w:rFonts w:eastAsia="Times New Roman" w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/><w:color w:val="00000A"/><w:sz w:val="22"/><w:szCs w:val="22"/><w:lang w:val="en-US"-US" w:bidi="ar-SA"/></w:rPr><w:t>etterDate.value|date:"Y-m-d"}}</w:t></w:r>"""
>>> re.sub(r"(\{\{[^}]+}\})", lambda m: re.sub("<[^>]+>", "", m.group(1)), s)
'<w:rPr><w:rFonts w:eastAsia="Times New Roman" w:cs="Arial" w:ascii="Arial" w:hAnsi="Arial"/><w:color w:val="00000A"/><w:sz w:val="22"/><w:szCs w:val="22"/><w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/></w:rPr><w:t>{{form.LetterDate.value|date:"Y-m-d"}}</w:t></w:r>'

解释,既然您要求指导,而不仅仅是答案;

re.sub(r"(\{\{[^}]+}\})", lambda m: re.sub("&quot;", '"', m.group(1)), word_docxml)

它的工作方式是首先匹配一个双括号间隔。 lambda 表达式仅采用在该匹配中找到的组并替换相关内容。

较小的正则表达式解释:

&quot;     # Just matching that, nothing fancy

匹配标签的模式;

<     # Opening of tag
[^>]+ # Followed by 1 or more characters that are not closing tags
>     # Followed by a closing tag

【讨论】:

  • 鉴于这些是他正在使用的 django 模板,双括号内不会有任何单括号。不过,我同意您的观点,即在您提出的某些情况下,它会产生误报。
  • 最后,虽然 lambdas 需要一些时间来适应,但我相信最好把学生的精力放在它们身上,而不是制作或盯着一个无法轻易推理的 20 多个字符的正则表达式,并且允许在出乎意料的地方或时间出现误报或负阳性。这是一种学生也可以在更多地方利用的技术。我想说咬紧牙关 :) Lambdas 将使一个人成为更好的程序员以及更好的正则表达式大使。
  • @msw 这与解析 HTML 无关。完全没有。在这里仅仅链接是没有意义的,并暗示您可能不理解“解析”在该帖子的上下文中的实际含义。
  • @msw 澄清一下,那篇文章解释了为什么解析 HTML 是一个坏主意,因为 HTML 中没有严格的结构,浏览器可以处理和忽略 HTML 中经常编写的许多错误人类,这使得 HTML 成为一个脆弱的结构。这个问题是关于处理 django 模板代码,它确实具有 very 刚性结构,如果做错了会产生错误。使用正则表达式获取 HTML 代码的较小部分也没有错,只要您不尝试完整地阅读 DOM 结构。
  • } 是正则表达式中的特殊字符,用于匹配文字字符时需要转义。不需要第一个的原因是它在一个字符类中,大多数特殊字符在那里丢失或具有不同的含义。在大多数情况下,它们只是匹配它们真正代表的角色。
【解决方案2】:

在测试一个匹配度不高的正则表达式时必须小心(误报)。考虑到您的复杂输入,这变得更加重要。

例如,一个正则表达式不应该匹配

&quot;

下面

test { &quot; }}text
test  &quot; }}

至于你的第二个问题,我会在 2 遍中完成,以保持正则表达式的简洁

首先使用这个正则表达式来匹配 {{ 和 }} 之间的内容

\{\{(.*?)\}\}

现在只对组 1 的内容应用一个函数。 我熟悉 .NET,它允许这样做,我希望你的语言也这样做

要应用的函数又是一个没有任何内容的替换正则表达式

<[^>]*>

我希望我的 Python 方言是正确的。

第一个问题可以用同样的思路。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-04
    • 2015-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    • 2011-02-09
    相关资源
    最近更新 更多