我想从一些文件路径中获取文件的字母部分。
files = ['data/Conversion/201406/MM_CLD_Conversion_Advertiser_96337_Daily_140606.zip',
'data/Match/201406/MM_CLD_Match_Advertiser_111423_Daily_140608.csv.zip',
'data/AQlog/201406/orx140605.csv.zip',
'data/AQlog/201406/orx140605.csv.zip/']
目前我这样做:
os.path.splitext()
删除可能的2个文件扩展名代码:
for f in files:
a = os.path.splitext(os.path.splitext(os.path.split(f.rstrip('/\\'))[1])[0])[0]
b = re.sub('\d+', '', a).replace('_','')
结果:
'MMCLDConversionAdvertiserDaily'
'MMCLDMatchAdvertiserDaily'
'orx'
'orx'
使用编译的正则表达式函数是否有更快或更pythonic的方式?或者试图使用库os.path()
非常合理?我也不必这样做超过100次,所以这不是速度问题,这只是为了清晰。
答案 0 :(得分:2)
不使用正则表达式:
import os
import string
trans = string.maketrans('_', ' ')
def get_filename(path):
# If you need to keep the directory, use os.path.split
filename = os.path.basename(path.rstrip('/'))
try:
# If the extension starts at the last period, use
# os.path.splitext
# If the extension starts at the 2nd to last period,
# use os.path.splitext twice
# Continuing this pattern (since it sounds like you
# don't know how many extensions a filename may have,
# it may be safer to assume the file extension starts
# at the first period. In which case, use
# filename.split('.', 1).
filename_without_ext, extension = filename.split('.', 1)
except ValueError:
filename_without_ext = filename
extension = ''
filename_cleaned = filename_without_ext.translate(trans, string.digits)
return filename_cleaned
>>> path = 'data/Match/201406/MM_CLD_Match_Advertiser_111423_Daily_140608.csv.zip/'
>>> get_filename(path)
'MM CLD Match Advertiser Daily '
做任何更可读的方法。如果问题不需要,我通常会避免使用正则表达式。在这种情况下,常规字符串操作可以执行您想要执行的所有操作。
如果要删除多余的空格(如结果中所示),请使用filename.replace(' ', '')
。如果您可能有其他类型的空白,可以通过''.join(filename.split())
注意:如果您使用的是Python 3,请将trans=string.maketrans('_', ' ')
替换为trans=str.maketrans('_', ' ', string.digits)
,将filename_without_ext.translate(trans, string.digits)
替换为filename_without_ext.translate(trans)
。 This change是改进unicode语言支持的一部分。查看更多:How come string.maketrans does not work in Python 3.1?
这是Python 3代码:
import os
import string
trans = string.maketrans('_', ' ', string,digits)
def get_filename(path):
filename = os.path.basename(path.rstrip('/'))
filename_without_ext = filename.split('.', 1)[0]
filename_cleaned = filename_without_ext.translate(trans)
return filename_cleaned
答案 1 :(得分:2)
您可以使用os.path
中的相应功能来简化此操作。
首先,如果您致电normpath
,则不再需要担心这两种路径分隔符,只需os.sep
(请注意,如果您这样做,这是一个错误的事情)重新尝试,例如,在Linux上处理Windows路径......但如果您尝试在任何给定平台上处理本机路径,那么它正是您想要的)。它还会删除任何尾随斜杠。
接下来,如果您拨打basename
而不是split
,则无需再输入[1]
个帖子。
不幸的是,basename
没有split
与splitext
相当......但是您可以轻松编写一个,这将使您的代码更具可读性,其方式与使用{ {1}}。
至于其余部分......正则表达式是删除任何数字的明显方法(尽管你真的不需要那里的basename
)。而且,既然你已经有了一个正则表达式,那么将+
放在那里而不是分开进行可能会更简单。
所以:
_
当然,如果你把它作为一个函数包装起来,整个事情可能会更具可读性:
def stripext(p):
return os.path.splitext(p)[0]
for f in files:
a = stripext(stripext(os.path.basename(os.path.normpath(f))))
b = re.sub(r'[\d_]', '', a)
特别是因为您现在可以将循环转换为列表理解或生成器表达式或def process_path(p):
a = stripext(stripext(os.path.basename(os.path.normpath(f))))
return re.sub(r'[\d_]', '', a)
for f in files:
b = process_path(f)
调用:
map
我只是对速度感到好奇,因为我的印象是编译的正则表达式函数非常快。
嗯,是的,总的来说。但是,未编译的字符串模式也非常快。
当您使用字符串模式而不是编译的regexp对象时,会发生以下情况:
processed_files = map(process_path, files)
模块在已编译正则表达式的缓存中查找模式。因此,假设您在应用程序中不使用许多正则表达式,无论哪种方式,您的模式都只编译一次,并重复运行为编译表达式。使用未编译表达式的唯一额外成本是在缓存字典中查找它,这非常便宜 - 特别是当它是字符串文字时,所以它保证每次都是完全相同的字符串对象,因此它的哈希将被缓存为好吧,所以在第一次dict查找变成re
和数组查找之后。
对于大多数应用程序,您可以假设mod
缓存足够好,因此决定是否预编译正则表达式的主要原因是可读性。例如,当你有一个函数运行一系列复杂的正则表达式,其目的很难理解时,它肯定有助于为每个正则表达式命名,所以你可以写re
,在这种情况下,编译它们几乎是愚蠢的。