使用Python从另一个文件复制带有搜索值的行

时间:2017-08-21 11:52:14

标签: python python-3.x

我想用Python来:

  1. search_list文件中读取一行。
  2. 遍历source_file行。
  3. 如果找到行匹配,请将整行从source_file复制到export_file
  4. 重复步骤1-3,直到search_file用尽。
  5. source_file的内容是纯文本。样品:

    Act of Heroism  Instant 1W  Common  Magali Villeneuve
    Adorned Pouncer Creature — Cat 1/1  1W  Rare    Slawomir Maniak
    Angel of Condemnation   Creature — Angel 3/3    2WW Rare    Slawomir Maniak
    

    search_list文件也是一个带有关键字的纯文本,每行一个,如下例所示:

    Condemnation
    Heroism
    

    在Stackoverflow中花了一些时间之后,我有了当前的代码 - 目前无法使用:

    with open('list.txt', 'r') as search_list, \
            open('source_file.txt', 'r', encoding="utf8") as source_file:
    
        for line in search_list:
            searchquery = search_list.readlines()
    
            for line in source_file:
                current_line = line.split()
    
                if searchquery in current_line:
                    print (line)
    

    它什么都不返回。

    我试图弄清楚出了什么问题,到目前为止我找不到它。

    我后退了一步,尝试用字符串搜索,它有效!

    with open('list.txt', 'r') as search_list, \
            open('source_file.txt', 'r', encoding="utf8") as source_file:
    
        for line in source_file:        
            if "Heroism" in line:
                print (line)
    

    结果是:

    Act of Heroism  Instant 1W  Common  Magali Villeneuve
    

    有人能指出我顶级代码中的错误吗?

    非常感谢。

1 个答案:

答案 0 :(得分:2)

我将您的问题解释为您要输出包含某个子字符串的文件source_file.txt的每一行,并且这些子字符串位于另一个文件search_list.txt中。如果这是正确的,以下代码应该适合您:

import sys

with open('search_list.txt', 'r') as search_list:
    targets = [line.strip() for line in search_list]

with open('source_file.txt', 'r') as source_file:
    for line in source_file:
        if any(target in line for target in targets):
            sys.stdout.write(line)

其中search_lines.txt

Condemnation
Heroism

source_file.txt

Act of Heroism Instant 1W Common Magali Villeneuve
Adorned Pouncer Creature — Cat 1/1 1W Rare Slawomir Maniak
Angel of Condemnation Creature — Angel 3/3 2WW Rare Slawomir Maniak

这将正确输出

Act of Heroism Instant 1W Common Magali Villeneuve
Angel of Condemnation Creature — Angel 3/3 2WW Rare Slawomir Maniak

每行包含' Condemnation'或' Heroism'。

首先建立所有targets的列表,然后对source_file.txt中的每一行,检查是否有任何目标是该行的子串。你需要建立一个目标列表,就像你在Python中迭代一个文件一样,每一行都被消费了#39;所以你不能再在另一个for循环中重新开始。

if any(target in line for target in targets)的工作方式大致如下:

首先,它使用生成器表达式target in line for target in targets。这会为target in line中的每个target返回line(检查target是否为targets的子字符串)的值 - 它也可以有效地写为

with open('source_file.txt', 'r') as source_file:
    for line in source_file:
        matches = []
        for target in targets:
            matches.append(target in line)
        if any(matches):
            sys.stdout.write(line)

现在,any函数采用可迭代(类似于列表)并返回True,如果任何值为True(或等同于True)。它还具有短路的特性 - 一旦遇到True,它就会立即停止,如果有的话。这意味着代码可以非常准确地重写为

with open('source_file.txt', 'r') as source_file:
    for line in source_file:
        matches = []
        for target in targets:
            if target in line:
                sys.stdout.write(line)
                break

(这与有一个生成器表达式这一事实有关,它不会立刻评估整个事物,但是懒惰地一次给出一个值,这意味着不会做更多的工作而不是需要。)

顺便说一句,[line.strip() for line in search_list]是列表理解。这会为line.strip()中的每一行返回search_list列表。这可以改写为

    targets = []
    for line in search_list:
        targets.append(line.strip()

希望这有帮助。 Here是关于列表推导如何工作的一些有用的文档。我发现从[i ** 2 for i in range(10)]这样的简单例子开始通常很有用。如果您需要进一步澄清,请与我们联系。