【问题标题】:How to compare two files from filelist using regex?如何使用正则表达式比较文件列表中的两个文件?
【发布时间】:2018-01-28 09:16:22
【问题描述】:

文件正在从带有 os.listdir 的文件夹中读取。在我输入文件 r'^[1-9\w]{2}_[1-9\w]{4}[1][7][\d\w]+\.[\d\w]+' 的正则表达式和另一个文件 r'^[1-9\w]{2}_[1-9\w]{4}[1][8]+' 的类似表达式之后。比较的条件是当前七个符号匹配时 os.remove(os.path.join(dir_name, each)) 。几个例子:bh_txbh171002.xml, bh_txbh180101.xml, ce_txce170101.xml... 据我了解,我们不能使用 match,因为没有任何字符串并且它返回 None,而且它仅将文件与正则表达式进行比较。我正在考虑条件if folder.itself(file) and file.startswitch("......."): 但不知道如何将文件名的前七个符号指向应该比较的内容。

老实说,我在那个请求中放置了我最差的代码版本,从那时起我学到了更多:the link - press to check it up

【问题讨论】:

  • 您的第一个正则表达式等于^\w{2}_\w{4}17\w+\.\w+,第二个正则表达式等于^\w{2}_\w{4}18+。现在,你想对他们做什么?他们是否按预期工作,如果没有,问题是什么?请提供具有预期行为的示例字符串。
  • @Wiktor Stribiżew 我想比较具有相同格式的每个文件,以及它们是否具有相似的开头(7 个符号相等),然后删除包含 17 的文件并保留 18。对于列表中的每个相似文件。
  • @Wiktor Stribiżew 我徒劳地尝试创建的代码在问题末尾的链接中提供。感谢您的提问

标签: python regex operating-system


【解决方案1】:

这里的正则表达式是错误的工具我没有你的文件,所以我创建了随机演示数据:

import random
import string

random.seed(42)  # make random repeatable 

def generateFileNames(amount): 
    """Generate 2*amount of names XX_XXXX with X in [a-zA-T0-9] with duplicates in it"""

    def rndName():
        """generate one random name XX_XXXX with X in [a-zA-T0-9]"""
        characters = string.ascii_lowercase + string.digits
        return random.choices(characters,k=2)+['_']+random.choices(characters,k=4)

    for _ in range(amount):  # create 2*amount names, some duplicates
        name = rndName()
        yield ''.join(name)          # yield name once
        if random.randint(1,10) > 3: # more likely to get same names twice
            yield ''.join(name)          # same name twice
        else: 
            yield ''.join(rndName())     # different 2nd name


def generateNumberParts(amount):
    """Generate 2*amount of 6-digit-strings, some with 17+18 as starting numbers"""
    def rndNums(nr):
        """Generate nr digits as string list"""
        return random.choices(string.digits,k=nr)

    for _ in range(amount):
        choi = rndNums(4)
        # i am yielding 18 first to demonstrate that sorting later works
        yield ''.join(['18']+choi)    # 18xxxx numbers
        if random.randint(1,10) > 5:
            yield ''.join(['17']+choi) # 17xxxx  
        else: 
            yield ''.join(rndNums(6)) # make it something other


# half the amount of files generated 
m = 10

# generate filenames
filenames = [''.join(x)+'.xml' for x in zip(generateFileNames(m),
                                     generateNumberParts(m)]

现在我有我的名字作为列表,可以开始找出哪些是具有较新时间戳的骗子:

# make a dict out of your filenames, use first 7 as key
# with list of values of files starting with this key a values:

fileDict={}
for names in filenames:
    fileDict.setdefault(names[0:7],[]).append(names) # create key=[] or/and append names

for k,v in fileDict.items():
    print (k, "    " , v)

# get files to delete (all the lower nr of the value-list if multiple in it)

filesToDelete = []

for k,v in fileDict.items():
    if len(v) == 1: # nothing to do, its only 1 file
        continue
    print(v, " to ", end = "" )         # debugging output
    v.sort(key = lambda x: int(x[7:9])) # sort by a lambda that integerfies 17/18
    print (v)                           # debugging output
    filesToDelete.extend(v[:-1])        # add all but the last file to the delete list

print("")
print(filesToDelete)

输出:

# the created filenames in your dict by "key      [values]"
xa_ji0y      ['xa_ji0y188040.xml', 'xa_ji0y501652.xml']
v3_a3zm      ['v3_a3zm181930.xml']
mm_jbqe      ['mm_jbqe171930.xml']
ck_w5ng      ['ck_w5ng180679.xml', 'ck_w5ng348136.xml']
zy_cwti      ['zy_cwti184296.xml', 'zy_cwti174296.xml']
41_iblj      ['41_iblj182983.xml', '41_iblj172983.xml']
5x_ff0t      ['5x_ff0t187453.xml']
sd_bdw2      ['sd_bdw2177453.xml']
vn_vqjt      ['vn_vqjt189618.xml', 'vn_vqjt179618.xml']
ep_q85j      ['ep_q85j185198.xml', 'ep_q85j175198.xml']
vf_1t2t      ['vf_1t2t180309.xml', 'vf_1t2t089040.xml']
11_ertj      ['11_ertj188425.xml', '11_ertj363842.xml']

# sorting the names by its integer at 8/9 position of name
['xa_ji0y188040.xml','xa_ji0y501652.xml'] to ['xa_ji0y188040.xml','xa_ji0y501652.xml']
['ck_w5ng180679.xml','ck_w5ng348136.xml'] to ['ck_w5ng180679.xml','ck_w5ng348136.xml']
['zy_cwti184296.xml','zy_cwti174296.xml'] to ['zy_cwti174296.xml','zy_cwti184296.xml']
['41_iblj182983.xml','41_iblj172983.xml'] to ['41_iblj172983.xml','41_iblj182983.xml']
['vn_vqjt189618.xml','vn_vqjt179618.xml'] to ['vn_vqjt179618.xml','vn_vqjt189618.xml']
['ep_q85j185198.xml','ep_q85j175198.xml'] to ['ep_q85j175198.xml','ep_q85j185198.xml']
['vf_1t2t180309.xml','vf_1t2t089040.xml'] to ['vf_1t2t089040.xml','vf_1t2t180309.xml']
['11_ertj188425.xml','11_ertj363842.xml'] to ['11_ertj188425.xml','11_ertj363842.xml']

# list of files to delete
['xa_ji0y188040.xml', 'ck_w5ng180679.xml', 'zy_cwti174296.xml', '41_iblj172983.xml', 
 'vn_vqjt179618.xml', 'ep_q85j175198.xml', 'vf_1t2t089040.xml', '11_ertj188425.xml']

【讨论】:

  • 这很好,几乎可以工作。我正在尝试将其应用于 os.listdir() 并检查结果。它会比较列表中的项目,但也会删除 xa_ji0y18XX...。我会尝试比较文件,只留下 18 个文件。非常感谢这个想法
  • @AlexanderLarionov 它删除了 18,因为在按 int 排序时,值列表中有 50、34 和 60 胜过其中包含 18 的文件。这是由于我的随机演示数据,您的数据应该没问题。您可以简单地将您的目录的文件名插入for names in filenames:,然后查看您的哪些文件名将被删除。
  • 我明白了。谢谢你,先生。工作。结果将被公布。完美的例子是什么让我的大脑紧张。
【解决方案2】:

我不明白我的代码有什么问题。在那里我从某个文件夹定义了列表,这样我就可以处理每个文件中的字符串,对吧?然后我应用过滤条件并进一步选择要删除的一个文件。

import os


dir_name = "/Python/Test_folder/Schems"
filenames = os.listdir(dir_name)

for names in filenames:

filenames.setdefault(names[0:7],[]).append(names) # create key=[] or/and append names
for k,v in filenames.items():

filesToDelete = []      #ther's a syntax mistake. But I can't get it - there's the list or not?

for k,v in filenames.items():
if len(v) == 1:
   continue
      v.sort(key = lambda x: int(x[7:9]))
      filesToDelete.extend(v[:-1])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    • 2017-10-08
    • 1970-01-01
    • 2018-08-01
    • 2013-06-26
    • 2013-12-24
    相关资源
    最近更新 更多