2012-10-19 54 views
13

sed專家的另一個問題。使用sed和正則表達式從字符串中提取數字

我有一個字符串表示一個路徑名,它將有兩個數字。一個例子是:

./pentaray_run2/Trace_220560.dat 

我需要提取這些數字的第二個 - 用即220560

我有(從論壇一些幫助)能夠所有的數字提取在一起(即2220560) :

sed "s/[^0-9]//g" 

或提取只與第一個數字:

sed -r 's|^([^.]+).*$|\1|; s|^[^0-9]*([0-9]+).*$|\1|' 

但我AFTE什麼r是第二個數字!任何幫助非常感謝。

PS我以後的號碼總是字符串中的第二個數字。

回答

12

這是好嗎?

sed -r 's/.*_([0-9]*)\..*/\1/g' 

你的榜樣:

kent$ echo "./pentaray_run2/Trace_220560.dat"|sed -r 's/.*_([0-9]*)\..*/\1/g' 
220560 
+0

偉大的作品一種享受。我猜這裏的_是否意味着在下劃線之後才能查找數字?在這種情況下,我總是可以期待一個下劃線,所以這將工作。表達式的哪一點實際上就是這樣。* _ St​​ackoverflow真的是一個非常棒的資源 - 我一直在困惑這個好幾個小時。出於興趣,你認爲有一種方法可以在最後使用\ 1 - 也許將所有數字(連續的數字)作爲子字符串提取並請求第二個數字。這對我和未來的其他人有用嗎? – Steven

6

如果grep歡迎:

$ echo './pentaray_run2/Trace_220560.dat' | grep -oP '\d+\D+\K\d+' 
220560 

,更便於攜帶與Perl具有相同的正則表達式:

echo './pentaray_run2/Trace_220560.dat' | perl -lne 'print $& if /\d+\D+\K\d+/' 
220560 

我想這種方法比使用sed

6

可以提取與這個最後的數字清潔&更穩健:

sed -e 's/.*[^0-9]\([0-9]\+\)[^0-9]*$/\1/' 

這是比較容易向後想這:

  1. 從字符串的結尾,匹配零個或多個非數字字符
  2. 匹配(並捕獲)一個或多個數字字符
  3. 匹配至少一個非數字字符
  4. 匹配所有字符的字符串的開頭

本場比賽的第3部分是這裏的「魔術」發生,但同時也限制了你的比賽至少有一個非數字前的數字(即。儘管有一個簡單的解決方法,即將非數字插入到字符串的開始位置,但不能與只有一個數字的字符串匹配。

魔法是反對.*(第4部分)的從左到右的貪婪。如果沒有第3部分,第4部分將會消耗所有它可以包含的數字,但是對於它來說,匹配可以確保它停止,以便至少允許一個非數字後跟一個數字被第1部分和第2部分消耗掉,允許捕獲號碼。

5

這可能爲你工作(GNU SED):

sed -r 's/([^0-9]*([0-9]*)){2}.*/\2/' file 

這提取第二個數字:

sed -r 's/([^0-9]*([0-9]*)){1}.*/\2/' file 

這種提取第一。