2009-02-24 94 views
1

我今天早些时候需要一个utililty函数来从文件中去掉一些数据,并写一个appaling常规表达式来完成它。输入是与许多线的与所述格式的文件:正则表达式教程,我该如何改进这个

<address> <11 * ascii character value>  <11 characters> 
00C4F244 75 6C 74 73 3E 3C 43 75 72 72 65 ults><Curre 

我想去掉一切在端杆的11个字符,并用于下面的表达式:

"^[0-9A-F+]{8}[\\s]{2}[0-9A-F\\s]{34}" 

这匹配于我不想从原始字符串中删除的位。我想看看你会怎么做,但我不能工作的特定领域是:

1:使正则表达式引擎返回我想要的字符,而不是我没有的字符和

2:找到一种重复匹配的方法,在一个单一的ASCII值后加空格(例如“75”= [0-9A-F] {2} [\ s] {1}?)并重复11次而不是抓取34个字符。

再看一遍最简单的事情就是匹配每个输入行的最后11个字符,但这不是很灵活,为了学习正则表达式我想看看你如何匹配从序列的开始。

编辑:谢谢你们,这是我想要的东西:

"(?:^[0-9A-F]{8} )(?:[0-9A-F]{2}){11} (.*)" 

希望我可以把你的绿色不止一个。

回答

1

1)^ [0-9A-F +] { 8} [\ s] {2} [0-9A-F \ s] {34}(。*)

Parens用于提取分组。如何检索它取决于你的语言环境,但现在某种$ 1被设置为初始模式之后的所有内容。

2)^ [0-9A-F +] {8} [\ s]的{2}(?:[0-9A-F \ S]){11} \ S(*)

(?:)是不提取的分组。所以(?:[0-9A-F \ s]){11}将子模式视为一个单元,并重复查找它11次。

顺便说一下,我在这里假设PCRE。

5

由于文件具有固定格式,因此您可以使用此正则表达式来匹配最后11个字符。

^.{44}(.{11}) 
0

地址和ASCII字符值是十六进制的所有这样:

^[0-9A-F \ S] {42}

2

过去十是:

...........$ 

或:

.{11}$ 

匹配一个十六进制字节+空间和重复十一次:

([0-9A-Fa-f]{2}){11} 
0

匹配行的末尾会

.{11}$ 

要仅匹配最后,您可以使用积极的背后。

"(?<=(^[0-9A-F+]{8}[\\s]{2}[0-9A-F\\s]{34}))(.*?)$" 

这将匹配任何字符,直到行末,提供,它是由“看后面”表达之前。

(?< = ....)定义了匹配前必须满足的条件。

我有点儿缺乏时间,但是如果你在网上查看包含单词“regex”和“lookbehind”的任何教程,你会发现很好的东西(如果正则表达式教程包括前后看,它通常会非常完整和先进)。

另一个建议是获得一个正则表达式培训工具,并与它一起玩。看看这个优秀的Regex designer

+0

带有后视声明的人会导致可怕的回溯。不要使用它。 – Gumbo 2009-02-24 15:16:46

0

如果您使用的是Perl,则还可以使用unpack()来获取每个元素。

my @data; 

open my $fh, '<', $filename or die; 
for my $line(<$fh>){ 
    my($address,@list) = unpack 'a8xx(a2x)11xa11', $line; 
    my $str = pop @list; 

    # unpack the hexadecimal bytes 
    my $data = join '', map { pack 'H2',$_ } @list; 

    die unless $data eq $str; 

    push @data, [$address,$data,$str]; 
} 
close $fh; 

我还继续和转换的11个十六进制代码回字符串,使用pack()