2010-06-30 58 views
1

我有幾個字符串,看起來像下面這樣:我會用什麼樣的正則表達式來匹配它?

<some_text> TAG[<some_text>@11.22.33.44] <some_text> 

我想從該行的IP_ADDRESS,只有IP_ADDRESS。 (爲了這個例子,假設IP地址將始終是這種格式xx.xx.xx.xx)

編輯:恐怕我不清楚。

的字符串會是這個樣子:

<some_text> TAG1[<some_text>@xx.xx.xx.xx] <some_text> TAG2[<some_text>@yy.yy.yy.yy] <some_text> 

注意「SOME_TEXT」可以是可變長度。我需要將不同的正則表達式關聯到不同的標記,以便當調用r.group()時,將返回IP地址。在上述情況下,正則表達式不會有所不同,但它是一個不好的例子。

到目前爲止我嘗試過的正則表達式已經不夠充分。

理想情況下,我想是這樣的:

r = re.search('(?<=TAG.*@)(\d\d.\d\d.\d\d.\d\d)', line) 

,其中線是上面指定的格式。但是,這不起作用,因爲您需要具有固定寬度的後視斷言。

此外,我也試過非捕獲組這樣:

r = re.search('(?<=TAG\[)(?:.*@)(\d\d.\d\d.\d\d.\d\d)', line) 

但是,我不能用這個,因爲r.group()將返回[email protected]

我知道r.group(1)將只返回ip地址。不幸的是,我寫的腳本要求我的所有正則表達式在調用r.group()後都會返回正確的結果。

這種情況我可以使用什麼樣的正則表達式?

代碼是在Python中。

注:所有SOME_TEXT可以是可變長度

+2

我認爲這個問題不是正則表達式,但是你必須使用'r.group()'。可能更容易擺脫這個要求;如果它導致這樣的問題,則很可能表明設計錯誤。 – Philipp 2010-06-30 18:23:35

回答

1

我不認爲這是可能的--r.group()將始終返回匹配的整個字符串,所以你不得不使用lookbehind,正如你所說的,它必須是固定的寬度。

相反,我會建議修改您正在編寫的腳本。我猜你有一整套匹配的正則表達式,並且你不想爲每一個指定「這個使用r.group(0)」,「這個使用r.group(3 )」等

在這種情況下,你可以使用Python的命名組設備:您可以在正則表達式這樣命名組:

(?P<name>CONTENTS) 

然後檢索與r.group("name")什麼匹配。

我建議你在腳本中做的事情是:匹配正則表達式,然後測試是否設置了r.group("usethis")。如果是這樣 - 使用它;如果不是,那麼像以前一樣使用r.group()。

通過這種方式,您可以通過在正則表達式中指定組名usethis來應對這種尷尬的情況 - 但您的其他正則表達式不必知道或在意。

+0

問題與您提到的完全相同。我不想指定這個'tag'使用r.group(0),而這個'tag'使用r.group(3)。我曾考慮過使用python的名稱工具來查看響應,似乎是最好的選擇。 – 2010-06-30 18:37:16

1

爲什麼你要使用的集體或者屁股呢? re.search('TAG\[.*@(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\]')有什麼不對?

+0

當使用r.group()調用該正則表達式時,將返回整個部分:TAG [[email protected]]。我需要它,所以r.group()只返回ip_address – 2010-06-30 18:24:59

+0

對不起,在第一個\ d之前忘記了左括號。我編輯了它,現在應該是正確的。 – Frank 2010-06-30 18:27:38

+0

不應該是'{1,3}',而不是'{1-3}'? – JAB 2010-06-30 18:33:35

2

嘗試re.search('(?<[email protected])\d\d\.\d\d\.\d\d\.\d\d(?=\])', line)

實際上,re.search('\d\d\.\d\d\.\d\d\.\d\d', line)可能會爲您提供所需的內容,如果被檢查的字符串中唯一一次出現的xx.xx.xx.xx格式位於這些IP地址段中。

編輯:正如我的評論所述,要查找所有出現在字符串中的想要的模式,你只需要做re.findall(pattern_to_match, line)。所以在這種情況下,re.findall('\d\d\.\d\d\.\d\d\.\d\d', line)(或更一般地說,re.findall('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', line))。編輯2:從你的評論,這應該工作(tagname是你當前想要的IP地址的標記)。

r = re.search(tagname + '\[[email protected](?P<ip>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', line) 

然後你可以參考r.group("ip")像psmears說的。

...實際上,有一個簡單的方法可以使正則表達式更簡潔一些。

r = re.search(tagname + r'\[[email protected](?P<ip>(?:\d{1,3}\.?){4})', line) 

事實上,你甚至可以做到這一點:

r = re.findall('(?P<tag>\S+)\[[email protected](?P<ip>(?:\d{1,3}\.?){4})', line) 

這將返回您包含標籤及其關聯IP地址的列表,所以你就不必重新檢查任何一個字符串一旦你找到了匹配,如果你想引用來自同一個字符串的不同標籤的IP地址。

...其實,要分兩步進一步(往前走嗎?),你可以做到以下幾點:

r = dict((m.group("tag"), m.group("ip")) for m in re.finditer('(?P<tag>\S+)\[[email protected](?P<ip>(?:\d{1,3}\.?){4})', line)) 

或者在Python 3:

r = {(m.group("tag"), m.group("ip")) for m in re.finditer('(?P<tag>\S+)\[[email protected](?P<ip>(?:\d{1,3}\.?){4})', line)} 

然後r將是一個以標籤作爲關鍵字,IP地址作爲各自的值。

+0

問題是在字符串中有@xx.xx.xx.xx的多次出現 – 2010-06-30 18:33:03

+0

在這種情況下,您只需使用're.findall(pattern)' – JAB 2010-06-30 18:35:10

+0

我的歉意。這個問題我還不清楚。該字符串將如下所示:some_text TAG1 [[email protected]] some_text TAG2 [[email protected]] some_text。我需要它找到只是說yy.yy.yy.yy. – 2010-06-30 18:39:19

0

差不多,但我認爲你需要在開始時改變。*。 *?因爲可能必須在一行上多個標記(I相信 - ,因爲在該示例)

re.search('TAG(\d+)\[.*[email protected](\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})]') 

標籤ID將在第一反向引用和IP地址將在所述第二後參考