python访问循环内的下一行

Posted

技术标签:

【中文标题】python访问循环内的下一行【英文标题】:python access next line inside loop 【发布时间】:2019-11-11 18:34:48 【问题描述】:

以下是输入数据:

crypto map outside_map0 1 set peer 1.1.1.1
crypto map outside_map0 1 ikev1 transform-set ESP-AES-256-SHA
crypto map outside_map0 2 set peer 2.2.2.2
crypto map outside_map0 2 ikev1 transform-set ESP-AES-256-SHA
crypto map outside_map0 3 set peer 3.3.3.3
crypto map outside_map0 3 ikev1 transform-set ESP-AES-256-SHA
crypto map outside_map0 4 set peer 4.4.4.4
crypto map outside_map0 4 ikev1 transform-set ESP-3DES-SHA

我希望我的输出数据如下所示:

1, 1.1.1.1, ESP-AES-256-SHA
2, 2.2.2.2, ESP-AES-256-SHA
3, 3.3.3.3, ESP-AES-256-SHA
4, 4.4.4.4, ESP-3DES-SHA

我的当前脚本是这样的:

fo = open('***.txt', 'r')
for line in fo.readlines():
    list = line.split(" ")
    if "peer" in list:
        print list[3] + "," + list[6] + "," + next(list[6])

我很难理解下一个函数的用法。

【问题讨论】:

试图通过调用next来完成什么?你认为它应该如何工作?解释这对您有很大帮助。 在第 1 行中找到“peer”后,我需要一种访问第 2 行的方法。然后打破循环并转到第 3 行(该行中将有“peer”,然后带我到第 4 行以获取正在使用的密码)等等...... 我想也有一种“更清洁”的方法可以做到这一点。我根本没有嫁给我上面想出的东西 How do I read two lines from a file at a time using python的可能重复 @JoeScripter 你为什么不在第二行使用.split() 呢?此外,切换到 Python 3,您编写脚本时使用的 Python 版本将在 1 月结束。 【参考方案1】:

可以使用next 函数做你想做的事,但这不是解决这个问题的最简单、最容易理解的方法。我不建议在这里尝试使用next

您在文件中的行上有一个for 循环,但实际上您想一次读取两行,因为数据的每个“项目”取决于文件中的两行。我建议分三个部分解决这个问题:

    首先,设计一种将数据表示为对象(例如元组或namedtuple)的方式。 编写while 循环以一次读取文件的两行,从这两行中提取数据以创建一个对象,并将这些对象收集到一个列表中。 遍历对象列表,从每个对象中打印出您想要的数据。

第 2 部分的解决方案可能如下所示:

results = []

with open('***.txt', 'r') as f:
    line1, line2 = f.readline(), f.readline()
    while line1 and line2:
        _, _, _, id_number, _, _, ip_address = line1.split()
        algorithm = line2.split()[-1]
        obj = (id_number, ip_address, algorithm)
        results.append(obj)

        line1, line2 = f.readline(), f.readline()

【讨论】:

如果您的文件包含奇数行,这将忽略最后一行。 问题中描述的文件格式不能合法地有奇数行包含有意义的数据;我只是拒绝编写代码检查文件是否符合要求的格式。【参考方案2】:
with open("***.txt") as f:
    for index, (line1, line2) in enumerate(zip(f, f), start=1):
        peer_ip = line1.split()[-1]
        cipher_suite = line2.split()[-1]
        print(index, peer_ip, cipher_suite, sep=', ')

查看问题How do I read two lines from a file at a time using python

这只是获取每行的最后一个单词,一次两行。您还需要进行一些错误检查,例如

if "peer" not in line1.split(): 
    raise ValueError(f'Line index doesn\'t contain the word "peer", but it should: line1')

或尝试parse peer_ip as an IP address

import ipaddress


def is_valid_ip_address(text):
    try:
        ipaddress.ipaddress(text)
        return True
    except ValueError:
        return False


with open("***.txt") as f:
    for index, (line1, line2) in enumerate(zip(f, f), start=1):
        peer_ip = line1.split()[-1]
        cipher_suite = line2.split()[-1]

        if not is_valid_ip_address(peer_ip):
            raise ValueError(
                f'Line couldn\'t parse "peer_ip" as an IP address on line index'
            )

        print(index, peer_ip, cipher_suite, sep=", ")

【讨论】:

【参考方案3】:

你不能在 str 对象旁边使用。

这里是精确文件结构的解决方案

with open('***.txt', 'r') as fo
    desired_line = ''

    for line in fo:
        list = line.split(" ")
        if "peer" in list:
            desired_line += list[3] + "," + list[6].strip()
        else:
            desired_line += ", " + line.split(' ')[6]
            print(desired_line)
            desired_line = ''

【讨论】:

出于多种原因,强烈建议不要在内存中读取整个文件。请借此机会正确培训人 你可以只做for line in fo,你应该打开像with open('***.txt') as fo:这样的文件,这样你就不必.close()它们,它会自动发生。【参考方案4】:

您可以使用 pandas 轻松完成此操作。根据我所见,您的要求是获得第 4、6、7 列。我认为每一列都由 tab('\t') 分隔。您甚至可以使用空间。 我使用了虚拟列名。你可以使用合适的。

import pandas as pd
df = pd.read_csv('***.txt' , sep = '\t', header = None)
df.columns = ["A", "B", "C", "D", "E", "F", "G"]
OutputData = df[["D","F", "G"]]
OutputData.to_csv('***2.txt' , sep= '\t')

【讨论】:

以上是关于python访问循环内的下一行的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django 模板中获取 for 循环内的列表的下一个元素?

Sqlite检查一行中的值是不是在没有循环的下一行中的值之间

python之 迭代器,生成器

python 文件单行循环读取的坑(一个程序中,文件默认只能按行循环读取一次,即使写到另一个循环里,它也只读取一次)

获取循环中的下一项

重复循环内的行