打印特定模式之间的行

0 投票
2 回答
983 浏览
提问于 2025-04-17 18:54

我想要打印出特定字符串之间的内容,我的字符串如下:

my_string = '''
##start/file1
file/images/graphs/main
file/images/graphs
file/graphs

##start/new
new/pattern/symbol
new/pattern/

##start/info/version
version/info/main
version/info/minor

##start
values/key
values
...
... '''

在这个字符串中,我想搜索“main”,并把它打印出来,格式如下:

##start/file1/file/images/graphs/main
##start/info/version/version/info/main

我该怎么做呢?我试着在两个##start之间找到行,并搜索main。

2 个回答

0

有一种方法可以用Python的正则表达式解析器来实现,简称为regex。

简单来说,regex是一种用于在字符串中查找特定模式的语言。如果我有一个字符串'Hello, World',它会匹配正则表达式模式'llo, Wor',因为这个模式包含了一个“l”,后面跟着另一个“l”,再后面是一个“o”,然后是一个逗号和一个空格,接着是一个大写的“W”,依此类推。表面上看,这就像是在测试子字符串。正则表达式的真正强大之处在于它的特殊字符。如果我再次使用字符串'Hello, World',它也会匹配模式'Hello, \w\w\w\w\w',因为\w是一个特殊字符,代表字母表中的任何字母(还有一些额外的字符)。所以'Hello, Bobby''Hello, World''Hello, kitty'都能匹配模式'Hello, \w\w\w\w\w',因为\w可以代表任何字母。还有很多这样的“特殊字符”,它们都非常有用。为了回答你的问题,

我构造了一个匹配的模式

##start\textICareAbout
file_I_don't_care
file_I_don't_care
file_I_care_about\main

这个模式是

r'(##start{line}){line}*?(.*main)'.format(line=r'(?:.*\n)')

开头的r表示这个字符串是一个原始字符串(这样我们就不需要在换行符前面加双反斜杠,具体可以查看链接的网页)。然后,括号中的内容变成了一个组。组是我们想要稍后能够回忆起来的文本片段。这里有两个组。第一个是(##start{line}),第二个是(.*main)。第一个组匹配任何以##start开头并且持续整整一行的内容,比如 ##start/file1##start/new。 第二个组匹配以main结尾的行,因为.*匹配除了换行符以外的所有字符。在这两个组之间有{line}*,意思是“匹配任何完整的行,并且可以匹配任意数量的行”。所以把这些结合起来,我们得到: 匹配任何以##start开头的内容,然后匹配任意数量的行,最后匹配任何以main结尾的行。

import re

# define my_string here

pattern = re.compile(r'(##start{line}){line}*?(.*main)'.format(line=r'(?:.*\n)'))

for match in pattern.findall(my_string):
    string = match[0][:-1]  # don't want the trailing \n
    string += '/'
    string += match[1]
    print string

对于你的例子,它输出

##start/file1/file/images/graphs/main
##start/new/version/info/main

所以正则表达式非常酷,其他语言也有这个功能。它是一个非常强大的工具,你应该学习如何使用它,可以在这里找到相关资料。另外,我想提一下,我使用.format函数,因为我觉得它看起来更整洁、更易读,所以 'hello{line}world'.format(line=r'(?:.*\n)')会被计算为'hello(?:.*\n)world',并且它会匹配

hello
Any Text Here. Anything at all. (just for one line)
world
0

你可以试试下面这样的代码:

def get_mains(my_string):
    section = ''

    for line in my_string.split('\n'):
        if line[0:7] == "##start":
            section = line
            continue
        if 'main' in line:
            yield '/'.join([section, line])

for main in get_mains(my_string):
    print main

撰写回答