2009-02-24 68 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()