草庐IT

python - 将两个文件相互匹配并将输出写入文件 - Python

coder 2024-07-04 原文

我是 Python 新手。我第二次在里面编码。该脚本的要点是获取包含数千行文件名的文本文件(sNotUsed 文件)并将其与大约 50 个 XML 文件进行匹配。每个 XML 文件可能包含多达数千行,并且格式与大多数 XML 一样。到目前为止,我不确定代码的问题是什么。代码不完整,因为我没有添加将输出写回 XML 文件的部分,但当前的最后一行应该至少打印一次。但事实并非如此。

两种文件格式的例子如下:

文本文件:

fileNameWithoutExtension1
fileNameWithoutExtension2
fileNameWithoutExtension3
etc.

XML 文件:

<blocks> 

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

到目前为止我的代码:

import os
import re

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

xmlFiles=list() # list of xmlFiles in directory
usedS=list() # list of S files that do not match against sFile txt

search = "\w/([\w\-]+)"

# getting the list of xmlFiles
filelist=os.listdir('C:\Users\xxx\Desktop\dir')
for files in filelist:
    if files.endswith('.xml'):
        xmlFile = open(files, "r+") # open first file with read + write access
        xmlComp = xmlFile.readlines() # read lines and assign to list
        for lines in xmlComp: # iterate by line in list of lines
            temp = re.findall(search, lines)
            #print temp
            if temp:
                if temp[0] in sNotUsed:
                    print "yes" # debugging. I know there is at least one match for sure, but this is not being printed.

帮助清理问题: 对不起,我想我的问题不是很清楚。我希望脚本逐行检查每个 XML,并查看该行的 FILENAME 部分是否与 sNotUsed.txt 文件的确切行匹配。如果有匹配项,那么我想将其从 XML 中删除。如果该行与 sNotUsed.txt 中的任何行都不匹配,那么我希望它成为新修改的 XML 文件输出的一部分(它将覆盖旧文件)。如果仍然不清楚,请告诉我。

已编辑,工作代码

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)

最佳答案

有很多话要说,但我会尽量保持简洁。

PEP8:Python 代码风格指南

对于局部变量,您应该使用带下划线的小写字母。 看看 PEP8:Python 代码风格指南。

文件对象和with语句

使用with 语句打开文件,参见:文件对象:http://docs.python.org/2/library/stdtypes.html#bltin-file-objects

转义 Windows 文件名

Windows 文件名中的反斜杠会导致 Python 程序出现问题。您必须使用双反斜杠转义字符串或使用原始字符串。

例如:如果您的 Windows 文件名为 "dir\\notUsed.txt",您应该像这样转义它:"dir\\notUsed.txt" 或使用原始字符串 r"dir\notUsed.txt"。如果您不这样做,"\n" 将被解释为换行符!

注意:如果您需要支持 Unicode 文件名,您可以使用 Unicode 原始字符串:ur"dir\notUsed.txt"

另请参阅 StockOverFlow 中的问题 19065115。

将文件名存储在集合中:这是一个没有重复的优化集合

not_used_path = ur"dir\sNotUsed.txt"
with open(not_used_path) as not_used_file:
    not_used_set = set([line.strip() for line in not_used_file])

编译你的正则表达式

多次使用时编译正则表达式效率更高。同样,您应该使用原始字符串以避免反斜杠解释。

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

警告 os.listdir() 函数返回文件名列表而不是完整路径列表。请参阅 Python 文档中的此函数。

在您的示例中,您使用 os.listdir() 读取桌面目录 'C:\Users\xxx\Desktop\dir'。然后您想用 open(files, "r+") 打开此目录中的每个 XML 文件。但这是错误的,除非您当前的工作目录不是您的桌面目录。经典用法是像这样使用 os.path.join() 函数:

desktop_dir = r'C:\Users\xxx\Desktop\dir'
for filename in os.listdir(desktop_dir):
    desktop_path = os.path.join(desktop_dir, filename)

如果要提取文件名的扩展名,可以使用os.path.splitext() 函数。

desktop_dir = r'C:\Users\xxx\Desktop\dir'
for filename in os.listdir(desktop_dir):
    if os.path.splitext(filename)[1].lower() != '.xml':
        continue
    desktop_path = os.path.join(desktop_dir, filename)

你可以用一个理解列表来简化这个:

desktop_dir = r'C:\Users\xxx\Desktop\dir'
xml_list = [os.path.join(desktop_dir, filename)
            for filename in os.listdir(desktop_dir)
            if os.path.splitext(filename)[1].lower() == '.xml']

解析 XML 文件

如何解析一个XML文件?这是一个很好的问题! 有几种可能: - 使用正则表达式,高效但危险; - 使用 SAX 解析器,也很高效但令人困惑且难以维护; - 使用 DOM 解析器,效率较低但更清晰... 考虑使用 lxml 包(@see:http://lxml.de/)

这很危险,因为您读取文件的方式并不关心 XML 编码。这很糟糕!确实很糟糕! XML 文件通常以 UTF-8 编码。您应该首先解码 UTF-8 字节流。一种简单的方法是使用 codecs.open() 打开编码文件。

for xml_path in xml_list:
    with codecs.open(xml_path, "r", encoding="UTF-8") as xml_file:
        content = xml_file.read()

使用此解决方案,完整的 XML 内容作为 Unicode 字符串存储在 content 变量中。然后,您可以使用 Unicode 正则表达式来解析内容。

最后,您可以使用集合交集来查找给定的 XML 文件是否包含文本文件的通用名称。

for xml_path in xml_list:
    with codecs.open(xml_path, "r", encoding="UTF-8") as xml_file:
        content = xml_file.read()
    actual_set = set(pattern.findall(content))
    print(not_used_set & actual_set)

关于python - 将两个文件相互匹配并将输出写入文件 - Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19644869/

有关python - 将两个文件相互匹配并将输出写入文件 - Python的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  5. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  6. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  9. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  10. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

随机推荐