【问题标题】:Batch file rename: zero padding time with regex?批处理文件重命名:正则表达式的零填充时间?
【发布时间】:2019-04-08 17:24:34
【问题描述】:

我有一整套文件 (10.000+),文件名中包含日期和时间。问题是日期和时间没有补零,导致排序出现问题。

文件名格式为:output 5-11-2018 9h0m.xml
我想要的格式是:output 05-11-2018 09h00m.xml

我搜索了不同的解决方案,但大多数似乎都使用拆分字符串然后重新组合它们。这似乎很麻烦,因为在我的情况下,日、月、小时和分钟需要分开,填充然后重新组合。

我认为正则表达式可能会给我一些更好的解决方案,但我无法完全弄清楚。

我已经根据 Wiktor Stribiżew 的建议编辑了我的原始代码,即您不能在替换中使用正则表达式并改为使用组:

import os
import glob
import re

old_format = 'output [1-9]-11-2018 [1-2]?[1-9]h[0-9]m.xml'
dir = r'D:\Gebruikers\<user>\Documents\datatest\'   

old_pattern = re.compile(r'([1-9])-11-2018 ([1-2][1-9])h([0-9])m')

filelist = glob.glob(os.path.join(dir, old_format))
for file in filelist:
    print file
    newfile = re.sub(old_pattern, r'0\1-11-2018 \2h0\3m', file)
    os.rename(file, newfile)

但这仍然不能完全按照我的意愿运行,因为它不会改变 10 小时以下的时间。我还能尝试什么?

【问题讨论】:

  • 您不能在替换中使用正则表达式,在替换中使用正则表达式中的组和 \1\2 等占位符来引用这些值。请参阅re.sub docs。
  • 谢谢,这至少为我指明了正确的方向。这帮助我制定了一个可以更改至少部分文件名的 re.sub。但我真的很想找到一个解决方案,根据已经存在的位数(所以 1 -> 01 和 12 -> 12)对所有内容进行零填充。你还有更多指点吗?
  • r'0\1-11-2018 \2h0\3m'代替lambda x: '{}-11-2018 {}h{}m'.format(x.group(1).zfill(2), x.group(2).zfill(2), x.group(3).zfill(2))

标签: python regex rename filenames


【解决方案1】:

您可以使用作为替换参数传递给 re.sub 方法的 lambda 表达式使用 .zfill(2) 填充文件名中的数字。

另外,修复正则表达式模式以允许 1 或 2 位数字:(3[01]|[12][0-9]|0?[1-9]) 表示日期,(2[0-3]|[10]?\d) 表示一小时 (24 小时),([0-5]?[0-9]) 表示分钟:

old_pattern = re.compile(r'\b(3[01]|[12][0-9]|0?[1-9])-11-2018 (2[0-3]|[10]?\d)h([0-5]?[0-9])m')

请参阅regex demo

然后使用:

for file in filelist:
    newfile = re.sub(old_pattern, lambda x: '{}-11-2018 {}h{}m'.format(x.group(1).zfill(2), x.group(2).zfill(2), x.group(3).zfill(2)), file)
    os.rename(file, newfile)

请参阅 Python re.sub 文档:

如果repl 是一个函数,则每次出现pattern 时都会调用它。该函数采用单个匹配对象参数,并返回替换字符串。

【讨论】:

  • old_pattern 需要更改,因为它要求小时数为 2 位数。小时和分钟(或日/月)中的任何一个/两者都可以是个位数并且需要修复。但是您需要灵活,因为如果其他日期字段只有 1 位数字,您不希望有 2 位数字的日期字段导致它不匹配。带括号的 a|b 表达式可以完成这项工作,但会在整个地方重复一些正则表达式。
【解决方案2】:

为了简单起见,我建议使用更通用的 old_pattern,假设您的文件名仅与数字行为不端:

因为与需要在任何位置转换但在其他字段中为两位数的单个数字字段匹配的文件名组合需要很长的正则表达式才能更明确地列出,我建议使用这种更简单的方法来匹配要重命名的文件,这假设目录中只有这种匹配类型的文件,因为它更广泛地打开它,以便一目了然地编写和阅读 - 找到文件名中的任何单个数字字段(一个或多个) - IE。非数字,数字,非数字:

old_format = r'output\.*\D\d\D.*\.xml'

那么修复 re.sub 语句可以是:

newfile = re.sub(r'\D(\d)[hm-]', lambda x: x.group()[0]+x.group()[1].zfill(2)+x.group()[2], file)

除非设置了适当的 re 模块标志,否则这也会捕获 unicode 非 ascii 数字。

如果年份(例如 2018 年)可能只是“18”,那么它需要对此进行特殊处理 - 可能是单独的情况,并且还在 re.sub 正则表达式模式集中添加一个空格(即@987654323 @)。

【讨论】:

  • 我不喜欢对 .group() 的重复调用,但它是一个 lambda,因此无法保存在本地函数变量中。可以转换为一个,或者检查是否有更直接的访问。另一种选择是 lambda 内的迷你 re.sub() (我也认为那很丑)
猜你喜欢
  • 2018-06-14
  • 1970-01-01
  • 2021-05-12
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
  • 2014-02-05
  • 1970-01-01
  • 2016-08-22
相关资源
最近更新 更多