Regex 从行中提取子字符串

Regex 从行中提取子字符串,regex,perl,tcl,Regex,Perl,Tcl,我想匹配文件中几行中的两个子字符串。 e、 g.我这里有以下几行: DU.DUALGN.D3_D5H0TOD4B_RS1DQ.ELC.L2 DU.DUALGN.D3_D5H0TOD4B_RS2DQ.ELC.L2 EC.DU.DUAB0.D0_OPBQ.ELC.L2 我有上百万行,我只想提取包含DUALGN和ELC.L2的行 请帮助我如何为此编写正则表达式。Tcl比Perl更详细,这里: per

我想匹配文件中几行中的两个子字符串。 e、 g.我这里有以下几行:

                DU.DUALGN.D3_D5H0TOD4B_RS1DQ.ELC.L2

                DU.DUALGN.D3_D5H0TOD4B_RS2DQ.ELC.L2 

                EC.DU.DUAB0.D0_OPBQ.ELC.L2
我有上百万行,我只想提取包含DUALGN和ELC.L2的行


请帮助我如何为此编写正则表达式。

Tcl比Perl更详细,这里:

perl -ne 'print if /DUALGN/ and /ELC\.L2/' file
tclsh << 'END'
set fh [open "filename" r]
while {[gets $fh line] != -1} {
    if {[regexp {DUALGN} $line] && [regexp {ELC\.L2} $line]} {
        puts $line
    }
}
END

使用单个正则表达式:

如果我记得的话,这个版本使用了TCL8.1中引入的

^(?=.*DUALGN)(?=.*ELC\.L2)
这意味着:从字符串的开头开始,查找“DUALGN”,然后查找“ELC.L2”。您可以在Perl中使用相同的正则表达式

如果您的Tcl版本由于某种原因无法处理此问题,您可以这样做

(?:DUALGN.*ELC\.L2)|(?:ELC\.L2.*DUALGN)
这意味着:找到“DUALGN”,然后是“ELC.L2”,或者找到“ELC.L2”,最后是“DUALGN”


因为多纳尔创造了我;)——一些时间安排:

% set line "DU.DUALGN.D3_D5H0TOD4B_RS1DQ.ELC.L2"
DU.DUALGN.D3_D5H0TOD4B_RS1DQ.ELC.L2
% time {string match *DUALGN* $line; string match *ELC.L2* $line} 1000000
1.122276 microseconds per iteration
% time {string first DUALGN $line; string first ELC.L2 $line} 1000000
1.0179 microseconds per iteration
% time {regexp {^(?=.*DUALGN)(?=.*ELC\.L2)} $line} 1000000
12.840028 microseconds per iteration
% time {regexp {(?:DUALGN.*ELC\.L2)|(?:ELC\.L2.*DUALGN)} $line} 1000000
12.770246 microseconds per iteration
% time {regexp DUALGN $line; regexp ELC\\.L2 $line} 1000000
1.140218 microseconds per iteration

结论:选择使用一个正则表达式,您恰好选择了最慢的实现。

谢谢……我对tcl答案更感兴趣。您正在DUALGN和ELC\.L2之间使用here或“|”运算,但当我在一行中同时获得它们时,我的条件将为真。你能提供一些更多的见解吗?谢谢你,格伦!!谢谢你的帮助。但除此之外,我还有另一个棘手的情况。在这里,我只能使用regexp来提取行,并且(不能使用任何其他选项)也只能使用一个regexp(而不是两个)。实际上,我已经编写了一个内置regexp命令的C代码。我在这里解析一个tcl文件作为接口,这个tcl文件只有我想要提取的这些名称(DUALGN,ELC\.L2)。这些名称将与另一个包含数百万行的文本文件映射。因此,我很想知道如何使用单个regexp提取它们,这里
字符串匹配*DUALGN*$line
可能更快
time
it并确定(Tcl可能会在内部优化非常简单的
regexp
调用
string match
无论如何在内部…)@DonalFelllows,不完全是这样,是的,它看起来是这样。如果两者都存在,
DUALGN
是否总是在
ELC.L2
之前?那么
ELC.L2
是否总是在行的末尾?这些将有助于使RE更加优化。是的,DUALGN始终位于ELC.L2之前,但ELC.L2可能并不总是位于行的末尾
% set line "DU.DUALGN.D3_D5H0TOD4B_RS1DQ.ELC.L2"
DU.DUALGN.D3_D5H0TOD4B_RS1DQ.ELC.L2
% time {string match *DUALGN* $line; string match *ELC.L2* $line} 1000000
1.122276 microseconds per iteration
% time {string first DUALGN $line; string first ELC.L2 $line} 1000000
1.0179 microseconds per iteration
% time {regexp {^(?=.*DUALGN)(?=.*ELC\.L2)} $line} 1000000
12.840028 microseconds per iteration
% time {regexp {(?:DUALGN.*ELC\.L2)|(?:ELC\.L2.*DUALGN)} $line} 1000000
12.770246 microseconds per iteration
% time {regexp DUALGN $line; regexp ELC\\.L2 $line} 1000000
1.140218 microseconds per iteration