如何匹配两个文件并导出输出结果为文件 - Python

84 阅读4分钟

原帖发帖人希望用 Python 匹配两个文件的内容,并将输出结果写到一个文件中。第一个文件包含数千行文件名(称为 sNotUsed 文件),第二个文件包含大约 50 个 XML 文件。XML 文件可能包含数千行,并且遵循标准的 XML 格式。

原帖发帖人分享了代码的片段,但最后一行应该至少打印一次,但实际上并没有打印。

原帖发帖人希望脚本逐行遍历每个 XML 文件,并查看该行中的文件名部分是否与 sNotUsed.txt 文件的行完全匹配。如果有匹配项,则将其从 XML 中删除。如果该行与 sNotUsed.txt 文件中的任何行都不匹配,则希望将其作为新修改的 XML 文件(将覆盖旧文件)的输出的一部分。

2、解决方案

问题分析

原帖发帖人代码中的问题主要有以下几个方面:

  • 使用 open() 函数打开文件时,没有使用 with 语句。with 语句可以确保文件在使用后被正确关闭,即使在发生异常时也是如此。

  • 在使用正则表达式匹配文件名时,没有将正则表达式编译成模式对象,而是直接将正则表达式字符串传递给 findall() 函数。编译正则表达式可以提高匹配效率。

  • 在打开 XML 文件时,没有指定编码,这可能会导致 Unicode 编码错误。

  • 在写入 XML 文件时,没有使用 codecs.open() 函数,这可能会导致 Unicode 编码错误。

  • 在使用 os.listdir() 函数时,没有将目录的绝对路径传递给该函数,而是传递了目录名,这可能会导致问题。

解决方法

以下是原帖发帖人代码的修改版本,修复了上述问题:

import os
import re
import codecs

sFile = open("C:\Users\xxx\Desktop\sNotUsed.txt", "r") # open sNotUsed txt file
sNotUsed=sFile.readlines() # read all lines and assign to list
sFile.close() # close file

search = re.compile(r"\w/([\w-]+)")

sNotUsed=[x.strip().replace(',','') for x in sNotUsed]
directory=r'C:\Users\xxx\Desktop\dir'
filelist=os.listdir(directory) # getting the list of xmlFiles
# for each file in the list
for files in filelist:
    if files.endswith('.xml'): # make sure it is an XML file
        xmlFile = codecs.open(os.path.join(directory, files), "r", encoding="UTF-8") # open first file with read
        xmlComp = xmlFile.readlines() # read lines and assign to list
        print xmlComp
        xmlFile.close() # closing the file since the lines have already been read and assigned to a variable
        xmlEdit = codecs.open(os.path.join(directory, files), "w", encoding="UTF-8") # opening the same file again and overwriting all existing lines
        for lines in xmlComp: # iterate by line in list of lines
            #headerInd = re.search(search, lines) # used to get the headers, comments, and ending blocks
            temp = re.findall(search, lines) # finds all strings that match the regular expression compiled above and makes a list for each
            if temp: # if the list is not empty
                if temp[0] not in sNotUsed: # if the first (and only) value in each list is not in the sNotUsed list
                    xmlEdit.write(lines) # write it in the file
            else: # if the list is empty
                xmlEdit.write(lines) # write it (used to preserve the beginning and ending blocks of the XML, as well as comments)

代码说明

  1. sNotUsed 变量是一个列表,存储了 sNotUsed.txt 文件中的所有行。
  2. search 变量是一个正则表达式模式对象,用于匹配 XML 文件中的文件名。
  3. sNotUsed 变量中的每一行都被剥离了多余的空格并替换了逗号,以确保与 XML 文件中的文件名进行准确匹配。
  4. directory 变量存储了 XML 文件所在的目录的绝对路径。
  5. filelist 变量是一个列表,存储了 directory 目录中所有以 .xml 结尾的文件名。
  6. 对于 filelist 中的每个文件名,都会打开相应的 XML 文件并将其内容读取到 xmlComp 变量中。
  7. xmlFile 变量被关闭,以释放系统资源。
  8. 打开同一个 XML 文件进行写入,并将现有内容全部覆盖。
  9. 对于 xmlComp 中的每一行,都会使用正则表达式查找文件名。如果找到文件名,并且该文件名不在 sNotUsed 列表中,则将该行写入 XML 文件。
  10. 如果没有找到文件名,或者文件名在 sNotUsed 列表中,则将该行写入 XML 文件,以保留 XML 文件的开头和结尾块以及注释。

代码示例

假设 sNotUsed.txt 文件的内容如下:

fileNameWithoutExtension1
fileNameWithoutExtension2
fileNameWithoutExtension3

假设 dir 目录中有一个名为 file1.xml 的 XML 文件,其内容如下:

<blocks>

<more stuff="name">
     <Tag2>
        <Tag3 name="Tag3">
                 <!--COMMENT-->
                 <fileType>../../dir/fileNameWithoutExtension1</fileType>
                 <fileType>../../dir/fileNameWithoutExtension4</fileType>
</blocks>

运行上述修改后的代码后,file1.xml 文件的内容将变为:

<blocks>

<more stuff="name">
     <Tag2>
        <Tag3 name="Tag3">
                 <!--COMMENT-->
                 <fileType>../../dir/fileNameWithoutExtension4</fileType>
</blocks>

因为 fileNameWithoutExtension1sNotUsed.txt 文件中,所以它被从 XML 文件中删除了。