【问题标题】:Using Python to run nested string searches使用 Python 运行嵌套字符串搜索
【发布时间】:2014-07-11 13:17:12
【问题描述】:

我想知道是否有一种简单的方法可以在一个巨大的文本文件中运行嵌套搜索字符串?

我有一个文本文件,其中可能包含一行文本以突出显示特定问题区域。我正在研究可能的嵌套搜索,但也是为了避免在整个文本文件上对关联的第二个字符串运行全新的搜索,而是从第一个字符串匹配点继续。

例如,如果对文本文件运行字符串搜索并找到“问题字符串”,我希望然后运行辅助搜索或最好是继续搜索(从问题行)以找到第一个匹配项第二个搜索字符串。在我的情况下,第二个搜索字符串将找到最接近的“GPS INFO”字符串,然后从文本文件中收集 GPS 信息(即下一个连续的 GPS 字符串到第一个“问题字符串”)。

我希望这是有道理的?!?基本上我想避免对文本文件进行全新的搜索,而是继续从找到第一个字符串的位置进行搜索。

我在下面有一些代码,但这只是找到第一个字符串,如果我要寻找第二个字符串,我通常会开始新的搜索,但这并不能保证我找到下一个连续的字符串。

f = open(file, "r")    
searchlines = f.readlines()
searchstringsProblem = ['BIG Problem Line']
searchstringsGPSLoc = ['GPS INFO']

a = 0
tot = 0
row_num=0 # let it be current row number

while a<len(searchstringsProblem):
    for i, line in enumerate(searchlines):
        for word in searchstringsProblem:
            if word in line:
                prob = line.split()
                worksheet.write(2,0,"Problem ID:", bold) 
                worksheet.write(2,1,prob[5]) 
                break
    a = a+1

这是 GPS INFO 行的示例以及我希望收集的以下统计信息

Key line2 GPS Info

GPS = Active

Longitude = -0.00000

Latitude = +51.47700 

感谢收看。

米克

【问题讨论】:

  • 您是在寻找一个匹配项还是多个匹配项? IE。如果您发现一个问题/GPS 匹配,那么您就完成了,或者您想要所有配对。
  • 嗨 Bob,现在只是第一个匹配项,但我想将来我可能想要找到多个匹配项(日志文件中应该有几个问题区域),以便我可以绘制一个地图上的一系列 GPS 坐标。
  • @MikG 查看我的答案,我已添加对查找经度和纬度线的支持。

标签: python string


【解决方案1】:

您可以通过逐行遍历文件来跟踪行,而不是使用 .readlines() 将它们全部放在一个列表中。以下内容可能适合您的需求(它会发现所有问题/gps 对,请注意,如果没有以下 gps 对,它将不会发现问题):

文件:

random
random
random
GPS INFO: 238939
random
BIG Problem Line
random
blah GPS INFO: 238490
random GPS INFO: 325236342
BIG Problem Line2
GPS INFO: 12343

代码:

searchstringsProblem = 'BIG Problem Line'
searchstringsGPSLoc = 'GPS INFO'
matches = []

with open("test.txt") as f:
    problem = False
    problem_line = ""

    for line in f:
        if not problem and searchstringsProblem in line:
            problem_line = line.strip()
            problem = True
        elif problem and searchstringsGPSLoc in line:
            matches.append((problem_line, line.strip()))
            problem = False

print matches

这产生了我们:

[('BIG Problem Line', 'blah GPS INFO: 238490'), ('BIG Problem Line2', 'GPS INFO: 12343')]

如果您想跟踪行号,您可以使用 enumerate 遍历行,然后将其添加到附加值中。不确定您想如何存储所有匹配项,所以我只是假设了一个 list[(problem,gps)] 情况。


编辑: 更新了每 cmets 的经度/纬度支持:

文件:

random
random
random
GPS INFO: 238939
LONGITUDE: 123
LATITUDE: 321
random
BIG Problem Line
random
blah GPS INFO: 238490
LONGITUDE: 456
LATITUDE: 654
random GPS INFO: 325236342
LONGITUDE: 789
LATITUDE: 987
BIG Problem Line2
GPS INFO: 12343
LONGITUDE: 432
LATITUDE: 678

代码:

searchstringsProblem = 'BIG Problem Line'
searchstringsGPSLoc = 'GPS INFO'
matches = []

with open("test.txt") as f:
    problem = False
    problem_line = ""

    for line in f:
        if not problem and searchstringsProblem in line:
            problem_line = line.strip()
            problem = True
        elif problem and searchstringsGPSLoc in line:
            matches.append((problem_line, line.strip(), f.next().strip(), f.next().strip()))
            problem = False

for item in matches:
    print item

输出:

('BIG Problem Line', 'blah GPS INFO: 238490', 'LONGITUDE: 456', 'LATITUDE: 654')
('BIG Problem Line2', 'GPS INFO: 12343', 'LONGITUDE: 432', 'LATITUDE: 678')


EDIT2: 更新为在查找经度/纬度时忽略空白行:

文件:

BIG Problem Line

Key line2 GPS Info

GPS = Active

Longitude = -0.00000

Latitude = +51.47700

代码:

searchstringsProblem = 'BIG Problem Line'
searchstringsGPSLoc = 'GPS Info'
matches = []

with open("test.txt") as f:
    problem = False
    problem_line = ""

    for line in f:
        if not problem and searchstringsProblem in line:
            problem_line = line.strip()
            problem = True
        elif problem and searchstringsGPSLoc in line:
            latitude = ""
            longitude = ""
            for new_line in f:
                if "Longitude" in new_line:
                    longitude = new_line.split("=")[1].strip()
                elif "Latitude" in new_line:
                    latitude = new_line.split("=")[1].strip()
                if longitude and latitude:
                    break;

            if latitude and longitude:
                matches.append((problem_line, line.strip(), latitude, longitude))
                problem = False

for item in matches:
    print item

输出:

('BIG Problem Line', 'Key line2 GPS Info', '+51.47700', '-0.00000')

【讨论】:

  • 谢谢 Bob,我刚刚尝试过,效果很好!还有一个问题,在我之前的示例中,我列举了搜索行,以便我可以跳下几行以收集更多信息。在我的文本文件中,我有一个“GPS 信息”行,下一行给出“经度”,下一行给出“纬度”,然后我通常会在每行上进行拆分以提取两个 GPS 点,在您的示例中,这是否可以删除一两行?我想现在,与其搜索“GPS 信息”,我至少可以搜索“经度”开始
  • 您能详细说明一下吗?不确定您要在这里实现什么。您可以使用f.next() 转到下一行,这将再次跳行并返回下一行的字符串。因此,如果您还在寻找 GPS INFO 之后的下 2 行,您可以在 elif 循环中使用 f.next(),然后进行拆分。不确定您要获取什么信息。也许一个简短的示例文件会有所帮助。
  • 嗨,鲍勃,我已经添加了 GPS 信息的示例,并按照我想要获取的内容进行了添加。我已经尝试过您的更新,这看起来可行,只是我现在需要跳过空白行。
  • 添加了另一个更新,根据提供的文件应该适合您的场景。
  • 太棒了!谢谢鲍勃,这很好用。为我所有无知的问题道歉,我仍在学习最近从 Perl 迁移到 Python。你的例子应该让我忙一阵子。再次感谢!
【解决方案2】:

编辑:添加了获取经度和纬度的支持。 EDIT2: 正确拆分。

如果您想跟踪问题编号(即问题第一次发生、第二次发生等),您可以添加一些枚举或计数器,或者将else 添加到当前@987654322 @to 当你找到Big Problem Line时写一些文字。

def get_text_file(path):
    with open(path, "r") as f:
        searchstrings = ['BIG Problem Line', 'GPS INFO']
        current_string = 0
        for line in f:
            if searchstrings[current_string] in line:
                # That is, if the current index is 1 (you're looking for GPS info)
                if(current_string):
                    long_line = f.next()
                    lat_line = f.next()
                    long_value = long_line.split('=')[1]
                    lat_value = lat_line.split('=')[1]
                    some_write_function(long_value, lat_value) 
                current_string ^= 1 # Flips the bit (0^(1)=1, 1^(1)=0)

【讨论】:

  • 感谢 Al.Sal。我可以看到您的示例部分适用于我的文本文件,我对此进行了更多研究
  • 如果您的文本文件出现任何问题,请告诉我。
  • 嗨 Al.Sal,它正在寻找“大问题行”,但是当它继续在文本文件中进一步搜索 GPS 信息行时,它似乎停留在“大问题行” ' 然后从那里分裂,if(current_string): 行有问题。因此,如果找到“大问题线”,我需要继续搜索下一条“GPS INFO”线,然后从这个新点开始抓取和分割线
  • 真的吗?那很奇怪。它对我来说在格式相同的文件上工作得很好。
猜你喜欢
  • 1970-01-01
  • 2013-05-05
  • 2019-06-18
  • 2021-01-21
  • 2017-10-23
  • 1970-01-01
  • 2015-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多