Python:匹配之间的连续行,类似于awk 鉴于: 多行字符串字符串(已从文件中读取) 两个模式pattern1和pattern2,它们将匹配字符串中恰好一行的子字符串。这些线将被称为line1和line2
这些模式是正则表达式模式,但是如果这样做更容易的话,我可以更改它们的格式 搜索 我正在寻找一种方法来获取python中第1行和第2行之间的所有行(我们可以安全地假设第1行在第2行之前) 当然,这可以在for循环中完成,使用由Python:匹配之间的连续行,类似于awk 鉴于: 多行字符串字符串(已从文件中读取) 两个模式pattern1和pattern2,它们将匹配字符串中恰好一行的子字符串。这些线将被称为line1和line2,python,regex,string,awk,regex-lookarounds,Python,Regex,String,Awk,Regex Lookarounds,这些模式是正则表达式模式,但是如果这样做更容易的话,我可以更改它们的格式 搜索 我正在寻找一种方法来获取python中第1行和第2行之间的所有行(我们可以安全地假设第1行在第2行之前) 当然,这可以在for循环中完成,使用由pattern1设置的标志,并在pattern2匹配时中断。不过,我在这里寻找一个更紧凑的解决方案。这是awk中的一个简单的单行程序: awk '/pattern1/,/pattern2/' file 例子: 文件: 模式1:bb 模式2:dd 预期结果: bbb bb b
pattern1
设置的标志,并在pattern2
匹配时中断。不过,我在这里寻找一个更紧凑的解决方案。这是awk
中的一个简单的单行程序:
awk '/pattern1/,/pattern2/' file
例子:
文件:
模式1:bb
模式2:dd
预期结果:
bbb bb b
ccc cc c
ddd dd d
使用
regex
:
>>> print(a)
aaa aa a
bbb bb b
ccc cc c
ddd dd d
eee ee e
fff ff f
预期结果:
>>> print(re.search('^.*bb b$\n((:?.+\n)+)^.*dd d$',a, re.M).group())
bbb bb b
ccc cc c
ddd dd d
或仅随附文本:
>>> print(re.search('^.*bb b$\n((:?.+\n)+)^.*dd d$',a, re.M).group(1))
ccc cc c
使用re.DOTALL匹配任何内容,包括换行符。然后插入开始模式和结束模式:
re.search( '[\w ]*b bb.*?d dd[ \w]*', string, re.DOTALL).group(0)
re.search( '[\w ]*b bb.*?d dd[ \w]*', open('file').read(), re.DOTALL).group(0)
注意:(1)string
这是您要搜索的文件或字符串。(2) 您需要导入re
。如果您真的希望简洁,可能会有问题,您可以将读取文件和提取模式结合起来:
re.search( '[\w ]*b bb.*?d dd[ \w]*', string, re.DOTALL).group(0)
re.search( '[\w ]*b bb.*?d dd[ \w]*', open('file').read(), re.DOTALL).group(0)
在
awk
中,/start/,/end/
范围正则表达式打印/start/
所在的整行,包括找到/end/
模式的整行。它是一个有用的构造,已被Perl、sed、Ruby和其他人复制
要在Python中执行范围运算符,请编写一个类,该类跟踪上一次调用start
运算符直到end
运算符的状态。我们可以使用正则表达式(正如awk
所做的那样),也可以简单地修改为任何返回True
或False
状态的数据行
根据示例文件,您可以执行以下操作:
import re
class FlipFlop:
''' Class to imitate the bahavior of /start/, /end/ flip flop in awk '''
def __init__(self, start_pattern, end_pattern):
self.patterns = start_pattern, end_pattern
self.state = False
def __call__(self, st):
ms=[e.search(st) for e in self.patterns]
if all(m for m in ms):
self.state = False
return True
rtr=True if self.state else False
if ms[self.state]:
self.state = not self.state
return self.state or rtr
with open('/tmp/file') as f:
ff=FlipFlop(re.compile('b bb'), re.compile('d dd'))
print ''.join(line if ff(line) else "" for line in f)
印刷品:
bbb bb b
ccc cc c
ddd dd d
它保留了一行一行的文件读取,具有其他语言中所见的/start/,/end/
regex的灵活性。当然,您可以对多行字符串(假定名称为s
)执行相同的方法:
习惯上,在awk中,使用标志可以获得与触发器相同的结果:
$ awk '/b bb/{flag=1} flag{print $0} /d dd/{flag=0}' file
您也可以在Python中复制它(使用更多的单词):
也可以与内存中的字符串一起使用
或者,您可以使用多行正则表达式:
with open('/tmp/file') as f:
print ''.join(re.findall(r'^.*b bb[\s\S]*d dd.*$', f.read(), re.M))
但这需要将整个文件读入内存。由于您声明字符串已读入内存,因此在这种情况下,这可能是最简单的:
''.join(re.findall(r'^.*b bb[\s\S]*d dd.*$', s, re.M))
我想用python来做。(更正)有任何反馈吗?不捕获
pattern1
之前的行,也不捕获pattern2
之后的行的剩余部分。啊,OP更改了他想要的内容。编辑以适应。谢谢。这还不包括带bb
的行的开头或带dd
的行的结尾。整行需要从头到尾打印。现在它只匹配第2-n-1行。不要使用\n
使用re.M
,然后将^
和$
添加到您的模式中。@dawg,我认为数据匹配正确,不是吗?而且,使用re.M意味着我必须在模式中包含换行符。正则表达式^.+bb b$\n((:?。++\n)+^.+dd d$
至少需要在bb b
之前加一个字符,在dd d
之前加一个字符,因为+
vs.
''.join(re.findall(r'^.*b bb[\s\S]*d dd.*$', s, re.M))