【问题标题】:Python regex to remove whitespace inside a pattern matchPython正则表达式删除模式匹配中的空格
【发布时间】:2012-08-30 21:01:09
【问题描述】:

我有一些行为良好的 xml 文件,我想使用正则表达式重新格式化(不是解析!)。我们的目标是让每个 <trkpt> 对都成为单线。

以下代码有效,但我希望在单个正则表达式替换而不是循环中执行操作,因此我不需要将字符串连接回来。

import re

xml = """
    <trkseg>
      <trkpt lon="-51.2220657617" lat="-30.1072524581">
        <time>2012-08-25T10:20:44Z</time>
        <ele>0</ele>
      </trkpt>
      <trkpt lon="-51.2220657617" lat="-30.1072524581">
        <time>2012-08-25T10:20:44Z</time>
        <ele>0</ele>
      </trkpt>
      <trkpt lon="-51.2220657617" lat="-30.1072524581">
        <time>2012-08-25T10:20:44Z</time>
        <ele>0</ele>
      </trkpt>
    </trkseg>
"""

for trkpt in re.findall('<trkpt.*?</trkpt>', xml, re.DOTALL):
    print re.sub('>\s*<', '><', trkpt, re.DOTALL)

也欢迎使用sed 回答。

感谢阅读

【问题讨论】:

  • 你要的是trkseg还是trkpt作为一行?您声明 trkseg 但您的正则表达式适用于 trkpt...
  • 另外,我认为不管它是什么,都不可能有这种类型的嵌套标签?一旦你有嵌套,正则表达式将无法处理它。
  • 如果这是你正在做的“又快又脏”的脚本,并且你不想解析 xml,我会说 for 循环比疯狂的正则表达式更简单,更易读.
  • @DragonWraith 对不起,错字,确实是 trkpt...
  • @AlexanderKondratskiy 虽然是QnD的工作,但我想利用业余时间学习正则表达式。这是挑战的一部分:o)

标签: python regex string-substitution


【解决方案1】:

这个怎么样:

>>> regex = re.compile(
    r"""\n[ \t]*  # Match a newline plus following whitespace
    (?=           # only if... 
     (?:          # ...the following can be matched:
      (?!<trkpt)  #  (unless an opening <trkpt> tag occurs first)
      .           #  any character
     )*           # any number of times,
     </trkpt>     # followed by a closing </trkpt> tag
    )             # End of lookahead""", 
    re.DOTALL | re.VERBOSE)
>>> print regex.sub("", xml)

    <trkseg>
      <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
      <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
      <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
    </trkseg>

【讨论】:

  • 第一次对我不起作用。必须从多行模式和re.VERBOSE 标志中去除 cmets,如下所示:regex = re.compile('\n[ \t]*(?=(?:(?!&lt;trkpt).)*&lt;/trkpt&gt;)', re.DOTALL)。然后它起作用了,但是“吃掉”了缩进(不是大问题,我打算无论如何都要漂亮地打印结果)。
  • @heltonbiker:抱歉,当我将正则表达式更改为详细的正则表达式时,我忘记了字符串的 r 前缀。现在它应该可以正常工作了。很抱歉没有早点回答,但是当你写评论时已经过了午夜,我才刚刚读到它。
【解决方案2】:

这并不是您真正想要的,但为了成为单线,这里有一个单线:

>>> print re.sub(r'(<trkpt.*?</trkpt>)',
                 lambda m: re.sub(r'>\s*<', '><', m.group(1), re.DOTALL),
                 xml, flags=re.DOTALL)

<trkseg>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
</trkseg>

另请注意,如果任何字符串属性包含字符串"&lt;trkpt",这种方法将中断,这可能不会发生,但这是不使用真正解析器的问题。

【讨论】:

  • 这是一个不错的操作,但我担心额外的技巧会使代码难以阅读。还是谢谢!
【解决方案3】:

您想保留&lt;trkseg&gt; 吗?如果是这样,这可能对你有用:

print re.sub('([^gt])>\s*<', '\g<1>><', xml, re.DOTALL)

删除元素之间的所有空格,前提是前一个元素不以 t 或 g 结尾。

<trkseg>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44Z</time><ele>0</ele></trkpt>
</trkseg>

【讨论】:

  • 有效!你能解释一下这是如何/为什么起作用的吗?这里使用了哪些正则表达式概念?我无法确定它在命令中特定于 ...? 的位置
  • [^tg] 位匹配任何不是 t 或 g 的字符。它位于括号之间,因此它匹配的任何字符都可以通过替换字符串中的 \g 添加。
  • 是的,但在其他文件中仍然可能有带有gt 的标签,这会破坏技巧......:o(
  • 确实如此。如果有许多带有不同标签的文件,那么您将需要使用额外的知识,例如 ... 对中有多少元素,是否有更多嵌套...
【解决方案4】:

另一条线是

print re.sub("(<trkpt.+?>).*?(<time>.+?</time>).*?(<ele>.+?</ele>).*?(</trkpt>)",
             r'\1\2\3\4', xml, re.DOTALL)

生产

<trkseg>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt>
  <trkpt lon="-51.2220657617" lat="-30.1072524581"><time>2012-08-25T10:20:44</time><ele>0</ele></trkpt>
</trkseg>

这样的好处是便于为其他标签更改。

【讨论】:

  • 不幸的是,我不想依赖 内标签的具体顺序...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-08
相关资源
最近更新 更多