2014-03-24 125 views
0

我正在寫一個bash腳本,我需要從多個字符串中提取IPv4和IPv6地址範圍,然後在保存到文件之前根據需求對其進行格式化。提取Bash中的IPv4和IPv6地址範圍?

我已經得到了正則表達式做工精細:http://regexr.com?38jsb(不優化,大致增加)

然而,在bash它拋出,如果我有egrep其中規定egrep: repetition-operator operand invalid

這裏是我的bash腳本中使用的錯誤:

#!/bin/bash 

regex="(?>(?>([a-f\d]{1,4})(?>:(?1)){3}|(?!(?:.*[a-f\d](?>:|$)){})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f\d]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(?>\.(?4)){3}))\/\d{1,2}" 

echo "v=abc ip4:127.0.0.1/19 ip4:192.168.1.1/32 ip4:192.168.2.50/20 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all" | egrep -o $regex 

我該如何在bash中提取兩種類型的IP範圍?什麼是更好的解決方案?

注:我用樣本數據進行測試的目的,我

+3

未經檢驗的,但相當肯定'egrep'不會與一個數字,你正在使用運營商/類的工作(例如'\ D')。嘗試用'grep -Po'切換到Perl風格的正則表達式。你也應該引用'「$ regex」'。 – BroSlow

+0

不,那沒用!還有其他建議嗎?感謝您發佈btw! –

+0

你在使用GNU grep嗎? – BroSlow

回答

2

首先,單引號正則表達式變量賦值(regex='...')。

然後,使用grep -Po(和雙引號$regex),作爲@BroSlow建議(注意-P並不適用於所有平臺(例如,OSX)) - -P激活用於PCREs(Perl兼容正則表達式)支持,這是您的正則表達式所必需的。

爲了把它放在一起:

regex='(?>(?>([a-f\d]{1,4})(?>:(?1)){3}|(?!(?:.*[a-f\d](?>:|$)){})((?1)(?>:(?1)){0,6})?::(?2)?)|(?>(?>(?1)(?>:(?1)){5}:|(?!(?:.*[a-f\d]:){6,})(?3)?::(?>((?1)(?>:(?1)){0,4}):)?)?(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)(?>\.(?4)){3}))\/\d{1,2}' 
txt="v=abc ip4:127.0.0.1/19 ip4:192.168.1.1/32 ip4:192.168.2.50/20 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all" 
echo "$txt" | grep -Po "$regex" 

替代:繼@歐萊雅L'升的例子,這裏有一個大大簡化的解決方案,與樣本數據(再次依靠-P)的作品:

echo "$txt" | grep -Po '\bip[46]:\K[^ ]+' 

變了OSX,其中grep不發upport -P

echo "$txt" | egrep -o '\<ip[46]:[^ ]+' | cut -c 5- 
+0

現在,如果只有OS X grep有'-Po'選項,這些類型的事情會容易得多:) –

+2

@ l'l l:同意;我已經添加了簡化解決方案的OSX變體。 – mklement0

+0

@ mklement0感謝您的解決方案,簡化的解決方案比我的要好得多。完美:) –

2

這種模式應結合工作與sed的:

str="v=abc ip4:127.0.0.1/19 ip4:192.168.1.1/32 ip4:192.168.2.50/20 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all" 

echo $str | grep -s -i -o "ip[0-9]\:[a-z0-9\.:/]*" --color=always | sed 's/ip[0-9]\://g' 

輸出:

127.0.0.1/19 
192.168.1.1/32 
192.168.2.50/20 
2001:4860:4000::/36 
2404:6800:4000::/36 
2607:f8b0:4000::/36 
2800:3f0:4000::/36 
2a00:1450:4000::/36 
2c0f:fb50:4000::/36 

省略--color=always到如果需要,排除彩色輸出。

+0

感謝您的解決方案,我不得不使用@ mklement0解決方案,因爲它更簡單。 P.S雖然贊成。 –