Python 2:使用正则表达式从文本文件中提取整行,子字符串来自另一个

Python 2: Using regex to pull out whole lines from text file with substring from another

我有一个菜鸟问题。我在 Linux 系统上使用 python 2.7.6。

我想要实现的是使用列表中的特定数字(对应于 database 文本文件中的最后一个数字)来拉出 database 文本中的整行文件并打印它(稍后将该行写入另一个文本文件)。

我目前尝试使用的代码:

reg = re.compile(r'(\d+)$')

for line in "text file database":
    if list_line in reg.findall(line):
        print line

我发现我可以输入像

这样的字符串
list_line = "9"

并且它会输出相应数据库条目的整行就好了。但是尝试使用 list_line 在循环中一个一个地输入字符串是行不通的。

任何人都可以帮助我或指导我找到相关资源吗?

附录:

文本文件 database 文本文件包含类似于以下的数据:

gnl Acep_1.0 ACEP10001-PA 1
gnl Acep_1.0 ACEP10002-PA 2
gnl Acep_1.0 ACEP10003-PA 3
gnl Acep_1.0 ACEP10004-PA 4
gnl Acep_1.0 ACEP10005-PA 5
gnl Acep_1.0 ACEP10006-PA 7
gnl Acep_1.0 ACEP10007-PA 6
gnl Acep_1.0 ACEP10008-PA 8
gnl Acep_1.0 ACEP10009-PA 9
gnl Acep_1.0 ACEP10010-PA 10

搜索文本文件 list_line 类似于:

2
5
4
6

更新原始代码:

    #import extensions
    import linecache

    import re

    #set re.compiler parameters
    reg = re.compile(r'(\d+)$')

    #Designate and open list file
    in_list = raw_input("list input: ")

    open_list = open(in_list, "r")

    #Count lines in list file
    total_lines = sum(1 for line in open_list)

    print total_lines

    #Open out file in write mode
    outfile = raw_input("output: ")

    open_outfile = open(outfile, "w")

    #Designate db string
    db = raw_input("db input: ")

    open_db = open(db, "r")

    read_db = open_db.read() 

    split_db = read_db.splitlines()

    print split_db      

    #Set line_number value to 0
    line_number = 0

    #Count through line numbers and print line
    while line_number < total_lines:
        line_number = line_number + 1
        print line_number

        list_line = linecache.getline(in_list, line_number)
        print list_line

        for line in split_db:
            if list_line in reg.findall(line) :
                print line 

    #close files
    open_list.close()

    open_outfile.close()

    open_db.close() 

简短版本:您的 for 循环正在 "database" 文件一次,寻找相应的文本并停止。所以如果你有多行你想拉出来,比如在你的 list_line 文件中,你最终只会拉出一行。

此外,您查找行号的方式也不是个好主意。如果您要查找第 5 行,但第二行的数据中恰好有数字 5,会发生什么情况?例如,如果第二行看起来像:

gnl Acep_1.0 ACEP15202-PA 2

然后搜索“5”将return那一行而不是你想要的那一行。相反,由于您知道行号将是该行的最后一个数字,因此您应该利用 Python 的 str.split() 函数(它在空格上拆分字符串,而 return 是的最后一项,您可以使用 -1 作为列表索引来获取列表的最后一项,如下所示:

def get_one_line(line_number_string):
    with open("database_file.txt", "r") as datafile: # Open file for reading
        for line in datafile:  # This is how you get one line at a time in Python
            items = line.rstrip().split()
            if items[-1] == line_number_string:
                return line

我还没有谈到的一件事是 rstrip() 功能。当您遍历 Python 中的文件时,您会按原样获得每一行,其换行符仍然完好无损。稍后打印时,您可能会使用 print —— 但是 print 也会在您提供的内容末尾打印一个换行符。因此,除非您使用 rstrip(),否则您最终会得到两个换行符而不是一个,从而导致输出的每一行之间都有一个额外的空行。

您可能不熟悉的另一件事是 with 语句。无需过多介绍,这可确保在执行 return line 语句时关闭数据库文件。 with 工作原理的详细信息对于了解 Python 的人来说很有趣,但作为 Python 新手,您可能还不想深入研究它。请记住,当您打开文件时,请尝试使用 with open("filename") as some_variable: 并且 Python 会做正确的事情™。

好的。所以现在你有了 get_one_line() 函数,你可以像这样使用它:

with open("list_line.txt", "r") as line_number_file:
    for line in line_number_file:
        line_number_string = line.rstrip() # Don't want the newline character
        database_line = get_one_line(line_number_string)
        print database_line # Or do whatever you need to with it

注意: 如果您使用的是 Python 3,请将 print line 替换为 print(line):在 Python 3 中, print 语句变成了一个函数。

您可以使用此代码执行更多操作(例如,每次查找一行时都打开数据库文件效率很低——一次将整个内容读入内存,然后再查找您的数据会更好)。但这足以开始使用,如果您的数据库文件很小,那么您担心效率的时间将远远超过您只是以简单但较慢的方式进行操作所花费的时间。

所以看看这是否对您有帮助,如果有您不理解或不起作用的地方,请回来提出更多问题。

您可以从 list_line 文件的内容构建您的正则表达式模式:

import re

with open('list_line.txt') as list_line:
    pattern = list_line.read().replace('\n', '|')
    regex = re.compile('(' + pattern + ')$')

print('pattern = ' + regex.pattern)

with open('database.txt') as database:
    for line in database:
        if regex.search(line):
            print(line)