假定你的老板用电子邮件发给你上千个文件,文件名包含美国风格的日期 (MM-DD-YYYY),需要将它们改名为欧洲风格的日期(DD-MM-YYYY)。手工完成这个无聊的任务可能需要几天时间!让我们写一个程序来完成它。
下面是程序要做的事:
检查当前工作目录的所有文件名,寻找美国风格的日期。
如果找到,将该文件改名,交换月份和日期的位置,使之成为欧洲风格。 这意味着代码需要做下面的事情:
创建一个正则表达式,可以识别美国风格日期的文本模式。 调用 os.listdir(),找出工作目录中的所有文件。 循环遍历每个文件名,利用该正则表达式检查它是否包含日期。 如果它包含日期,用 shutil.move()对该文件改名。
对于这个项目,打开一个新的文件编辑器窗口,将代码保存为 renameDates.py。
import shutil,os,re
#AmerFile is MM-DD-YYYY
#EuroFile is DD-MM-YYYY
dataPattern=re.compile(r"""^(.*?)
((0|1)?\d)- # all text before the date
((0|1|2|3)?\d)- # one or two digits for the month
((19|20)\d\d) ## four digits for the year
(.*?)$ #all text after the date
""",re.VERBOSE)
for amerFilename in os.listdir('.'):
print("os.getcwd()=%s" %os.getcwd())
#os.listdir(path) 返回指定路径下所有文件和文件夹的名字,并存放于一个列表中。
mo=dataPattern.search(amerFilename)
if mo == None:
continue
beforePart=mo.group(1)
monthPart=mo.group(2)
dayPart=mo.group(4)
yearPart=mo.group(6)
afterPart=mo.group(8)
euroFilename=beforePart+dayPart+'-'+monthPart+'-'+yearPart+afterPart
absWorkingDir=os.path.abspath('.')
amerFilename=os.path.join(absWorkingDir,amerFilename)
euroFilename=os.path.join(absWorkingDir,euroFilename)
print('Renaming "%s" to "%s" ...' %(amerFilename,euroFilename))
# shutil.move(amerFilename,euroFilename) #will remove # after print test
Note:
贪心和非贪心匹配
在字符串'HaHaHaHaHa'中,因为(Ha){3,5}可以匹配 3 个、4 个或 5 个实例,你可能 会想,为什么在前面花括号的例子中,Match 对象的 group()调用会返回'HaHaHaHaHa', 而不是更短的可能结果。毕竟,'HaHaHa'和'HaHaHaHa'也能够有效地匹配正则表达 式(Ha){3,5}。
Python 的正则表达式默认是“贪心”的,这表示在有二义的情况下,它们会尽 可能匹配最长的字符串。花括号的“非贪心”版本匹配尽可能最短的字符串,即在 结束的花括号后跟着一个问号。
在交互式环境中输入以下代码,注意在查找相同字符串时,花括号的贪心形式 和非贪心形式之间的区别:
>>> greedyHaRegex = re.compile(r'(Ha){3,5}') >>> mo1 = greedyHaRegex.search('HaHaHaHaHa') >>> mo1.group()
'HaHaHaHaHa'
>>> nongreedyHaRegex = re.compile(r'(Ha){3,5}?') >>> mo2 = nongreedyHaRegex.search('HaHaHaHaHa') >>> mo2.group()
'HaHaHa'
使用了三重引号('"),创建了一个多行字符串。这样就可以 将正则表达式定义放在多行中,让它更可读。
而且,你可以告诉 re.compile(),忽略正则表达式字符 串中的空白符和注释,从而缓解这一点。要实现这种详细模式,可以向 re.compile() 传入变量 re.VERBOSE,作为第二个参数。这样表示正则表达式的多行字符串中,多余的空白字符 也不认为是要匹配的文本模式的一部分。这让你能够组织正则表达式,让它更可读。
如果希望正则表达式不区分大小写,并且句点字符匹配换行,就可以这 样构造 re.compile()调用:
>>> someRegexValue = re.compile('foo', re.IGNORECASE | re.DOTALL)
-
?匹配零次或一次前面的分组。
-
*匹配零次或多次前面的分组。
-
+匹配一次或多次前面的分组。
-
{n}匹配 n 次前面的分组。
-
{n,}匹配 n 次或更多前面的分组。
-
{,m}匹配零次到 m 次前面的分组。
-
{n,m}匹配至少 n 次、至多 m 次前面的分组。
-
{n,m}?或*?或+?对前面的分组进行非贪心匹配。
-
^spam 意味着字符串必须以 spam 开始。
-
spam$意味着字符串必须以 spam 结束。
-
.匹配所有字符,换行符除外。
-
\d、\w 和\s 分别匹配数字、单词和空格。
-
\D、\W 和\S 分别匹配出数字、单词和空格外的所有字符。
-
[abc]匹配方括号内的任意字符(诸如 a、b 或 c)。
-
[^abc]匹配不在方括号内的任意字符。
match()函数只检测字符串开头位置是否匹配,匹配成功才会返回结果,否则返回None。
search()函数会在整个字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
Reference:
1.https://www.cnblogs.com/aaronthon/p/9435967.html