Python 如何修复试图捕获单词和id的正则表达式?

Python 如何修复试图捕获单词和id的正则表达式?,python,regex,string,python-2.7,Python,Regex,String,Python 2.7,我有一个.txt文件,看起来像s字符串。s字符串由word\u 1和word\u 2一个id和一个number组成: word_1 word_2 id number 我想创建一个正则表达式,它在一个列表中捕获单词“nunca”的所有出现,后跟idVM\uuu提取“nunca”和VM\uuuuuuuu模式的构造是,眼波必须一个接一个地出现,其中是id字符串的自由字符,例如: nunca nunca RG 0.293030 first_word second_word VM223FDS 0.902

我有一个
.txt
文件,看起来像
s
字符串。
s
字符串由
word\u 1
word\u 2
一个
id
和一个
number
组成:

word_1 word_2 id number
我想创建一个正则表达式,它在一个列表中捕获单词
“nunca”
的所有出现,后跟id
VM\uuu
提取
“nunca”
VM\uuuuuuuu
模式的构造是,眼波必须一个接一个地出现,其中
id
字符串的自由字符,例如:

nunca nunca RG 0.293030
first_word second_word VM223FDS 0.902333
error errpr RG 0.345355667
nunca nunca RG 0.1489098
ninguna ninguno DI0S3DF 0.345344
third fourth VM34SDF 0.7865489
这是我想提取的模式,因为它们是一个接一个放置的。这将是列表中所需的输出:

[(nunca,RG),(second_word, VM223FDS)]
例如,这将是错误的,因为它们不是一个接一个的:

nunca nunca RG 0.293030
prendas prenda NCFP000 0.95625
success success VM23434SDF 0.902333
因此对于
s
字符串:

s = '''Vaya ir VMM03S0 0.427083
mañanita mañana RG 0.796611
, , Fc 1
buscando buscar VMG0000 1
una uno DI0FS0 0.951575
lavadora lavadora NCFS000 0.414738
con con SPS00 1
la el DA0FS0 0.972269
que que PR0CN000 0.562517
sorprender sorprender VMN0000 1
a a SPS00 0.996023
una uno DI0FS0 0.951575
persona persona NCFS000 0.98773
muy muy RG 1
especial especial AQ0CS0 1
para para SPS00 0.999103
nosotros nosotros PP1MP000 1
, , Fc 1
y y CC 0.999962
la lo PP3FSA00 0.0277039
encontramos encontrar VMIP1P0 0.65
. . Fp 1

Pero pero CC 0.999764
vamos ir VMIP1P0 0.655914
a a SPS00 0.996023
lo el DA0NS0 0.457533
que que PR0CN000 0.562517
interesa interesar VMIP3S0 0.994868
LO_QUE_INTERESA_La lo_que_interesa_la NP00000 1
lavadora lavador AQ0FS0 0.585262
tiene tener VMIP3S0 1
una uno DI0FS0 0.951575
clasificación clasificación NCFS000 1
A+ a+ NP00000 1
, , Fc 1
de de SPS00 0.999984
las el DA0FP0 0.970954
que que PR0CN000 0.562517
ahorran ahorrar VMIP3P0 1
energía energía NCFS000 1
, , Fc 1
si si CS 0.99954
no no RN 0.998134
me me PP1CS000 0.89124
equivoco equivocar VMIP1S0 1
. . Fp 1

Lava lavar VMIP3S0 0.397388
hasta hasta SPS00 0.957698
7 7 Z 1
kg kilogramo NCMN000 1
, , Fc 1
no no RN 0.998134
está estar VAIP3S0 0.999201
nada nada RG 0.135196
mal mal RG 0.497537
, , Fc 1
se se P00CN000 0.465639
le le PP3CSD00 1
veía ver VMII3S0 0.62272
un uno DI0MS0 0.987295
gran gran AQ0CS0 1
tambor tambor NCMS000 1
( ( Fpa 1
de de SPS00 0.999984
acero acero NCMS000 0.973481
inoxidable inoxidable AQ0CS0 1
) ) Fpt 1
y y CC 0.999962
un uno DI0MS0 0.987295
error error NCFSD23 0.234930
error error VMDFG34 0.98763
consumo consumo NCMS000 0.948927
máximo máximo AQ0MS0 0.986111
de de SPS00 0.999984
49 49 Z 1
litros litro NCMP000 1
error error DI0S3DF 1
Mandos mandos NP00000 1
intuitivos intuitivo AQ0MP0 1
, , Fc 1
todo todo PI0MS000 0.43165
muy muy RG 1
bien bien RG 0.902728
explicado explicar VMP00SM 1
, , Fc 1
jamas jamas RG 0.343443
nada nada PI0CS000 0.850279
que que PR0CN000 0.562517
ver ver VMN0000 0.997382
con con SPS00 1
la el DA0FS0 0.972269
lavadora lavadora NCFS000 0.414738
de de SPS00 0.999984
nunca nunca RG 0.903
casa casa NCFS000 0.979058
de de SPS00 0.999984
mis mi DP1CPS 0.995868
error error VM9032 0.234323
string string VMWEOO 0.03444
padres padre NCMP000 1
Además además NP00000 1
incluye incluir VMIP3S0 0.994868
la el DA0FS0 0.972269
tecnología tecnología NCFS000 1
error errpr RG2303 1
Textileprotec textileprotec NP00000 1
que que PR0CN000 0.562517
protege proteger VMIP3S0 0.994868
nuestras nuestro DP1FPP 0.994186
ninguna ninguno DI0S3DF 0.345344
falla falla NCFSD23 1
prendas prenda NCFP000 0.95625
más más RG 1
preciadas preciar VMP00PF 1
jamas jamas RG2303 1
string string VM9032 0.234323
nunca nunca RG 0.293030
success success VM23SDF 0.902333
. . Fp 1'''
这就是我尝试的

import re
pattern__ = re.findall(r'(?m)^.*?\b(nunca)\s+(\S+)\s+[0-9.]+\n.*?\s(\S+)\s+(VM\S+)\s+[0-9.]+$', s)

print pattern__
此aproach的问题在于它返回一个空白列表:
[]
。您是否知道如何解决此问题以获得:

[('nunca','RG'),('success','VM23SDF')]

提前感谢各位我想这个正则表达式有助于:

ur'.*?\b(nunca)\s+(\S+)\s+[0-9.]+[\r\n]+\S+\s+(\S+)\s+(VM\S+)\s+[0-9.]+'

请参阅。

您可以逐行解析文件,每次检查一对行:

import csv
with open("in.txt") as f:
    reader = csv.reader(f,delimiter=" ")
    prev = next(reader)
    for row in reader:
        if "VM" in row and "nunca" in prev:
            nun, val, = prev[-3:-1]
            wrd, i = row[-3:-1]
            print(nun, val, wrd, i)
        prev = row

('nunca', 'RG', 'success', 'VM')
比使用正则表达式快近20倍:

In [1]: %%timeit
   ...: with open("test.txt") as f:
   ...:     import re
   ...:     pr= re.findall(ur'.*?\b(nunca)\s+(\S+)\s+[0-9.]+[\r\n]+\S+\s+(\S+)\s+(VM)\s+[0-9.]+',f.read())
   ...: 
1000 loops, best of 3: 936 µs per loop

In [2]: import csv

In [3]: %%timeit
   ...: with open("test.txt") as f:
   ...:     reader = csv.reader(f,delimiter=" ")
   ...:     prev = next(reader)
   ...:     for row in reader:
   ...:         if "VM" in row and "nunca" in prev:
   ...:             nun, val, = prev[-3:-1]
   ...:             wrd, i = row[-3:-1]
   ...: 
10000 loops, best of 3: 59 µs per loop
对于您的更新:

import csv
with open(in.txt") as f:
    reader = csv.reader(f,delimiter=" ")
    prev = next(reader)
    for row in reader:
        if len(row) < 2:
            continue
        if row[-2].startswith("VM") and "nunca" in prev:
            nun, val, = prev[-3:-1]
            wrd, i = row[-3:-1]
            print(nun, val, wrd, i)
        prev = row

('nunca', 'RG', 'success', 'VM23SDF')

假设格式一致,如果我理解正确,可以只搜索
word_2
,那么正则表达式可以非常简单:

regex = re.compile("(nunca)\s(\S+)\s\d\S*\n\S+\s(\S+)\s(VM)", re.MULTILINE)
regex.findall(string)
我不是Python用户,我测试了我的正则表达式

更新约翰修正后,新正则表达式将为:

regex = re.compile("(nunca)\s(\S+)\s\d\S*\n\S+\s(\S+)\s(VM)(\S+)?", re.MULTILINE)
regex.findall(string)

这样,您将能够分别捕获VM和ID。如果你想把它们放在一起,只需切换到
(VM\S+)

哇,谢谢,我没有探索这个方法!。也许正则表达式很难完成这个任务!不用担心,
59µs vs 936µs
用于正则表达式。感谢您的帮助,我忘了提到
VM
id后面还有其他字符串。我必须捕获所有以
VM
模式作为第一个字符串的id。我编辑了这个问题。谢谢你的帮助,我忘了提到
VM
id后面跟着其他字符串。我必须捕获所有以
VM
模式作为第一个字符串的id。你知道怎么解决这个问题吗?。我编辑了这个问题。你能再检查一下吗?我刚刚将
\S+
添加回
(VM\S+
)。它似乎工作正常。请注意,csv和其他解析器可能非常好。尽管如此,我仍然相信正则表达式:)。感谢您的帮助,我忘了提到
VM
id后面跟着其他字符串。我必须捕获所有以
VM
模式作为第一个字符串的id。你知道如何解决这个问题吗?你是说VM加上一个数字,比如VM1234吗?是的,加上一个数字,比如
VM1234
或者字符串,比如
VM1234SDE
在我上次更新中,ID是可选的。它应该不会有什么坏处(我不确定输入格式),但如果您想强制执行,请删除regext末尾的问号
VM
id后面总是跟一组未定义的字符串和数字,例如:
VM998SFE
regex = re.compile("(nunca)\s(\S+)\s\d\S*\n\S+\s(\S+)\s(VM)(\S+)?", re.MULTILINE)
regex.findall(string)