2017-02-28 21 views
2
echo "A number is about to show up 1 and now I want to parse 365 guys and some extra junk" | sed -E 's/.*([0-9]+) guys.*/\1/g' 

上述命令目前輸出的只是5。本質上,我想用一個隨機句子來解析「球員」的數量,這個球員可以有數字(或者不是。我還想解析一下echo "365 guys")。我的.*36匹配,並且阻止它出現在\1中。我如何編寫sed命令(或任何其他正則表達式/ perl/awk)來完成我想要的?如何克服貪婪的匹配所有事情後再尋找一個特定的字符串?

回答

5

使用「節儉」量詞*?在Perl:

perl -pe 's/.*?([0-9]+) guys.*/$1/' 
+0

沒有理由讓'。*'完全在那裏 – Borodin

+0

@Borodin:有,你想替換它。當然還有其他方法來解決這個問題。 – choroba

+0

啊,我還沒有發現這是一個替代 – Borodin

1

由於您的號碼是一個空之前,你可以把它的正則表達式的一部分:

echo "A number is about to show up 1 and now I want to parse 365 guys and some extra junk" | sed -E 's/.* ([0-9]+) guys.*/\1/g' 

# => 365 
+0

偉大的建議,但我的句子可能並不總是在空間之前。回聲「365人和一些額外的垃圾」也是一個有效的輸入。我會讓問題更加健壯。謝謝你! –

2

隨着GNUgrep

$ grep -Po '\b[0-9]+(?= guys\b)' <<<"365 guys or 366 guys, but not foo12 guys." 
365 
366 
  • -P活性支持爲PCREs,這使先進的正則表達式功能。
  • -o指定只應打印輸入行的匹配部分。
  • \b僅匹配單詞邊界,包括在行首;
    這樣可以防止未獨立是guys開始匹配的數字號碼,但其他的詞,如在foo365 guys一部分,也就是說,如guysanddolls
  • (?= guys)是一個前瞻斷言,它匹配所包含的子表達式,但不會將其包含在返回的匹配字符串中。

作爲證明的,這可能匹配多個上的給定線圖案,用印刷萃取上其自身的輸出線中的每個號碼。
如果這是不希望的,grep不能使用,因爲-o總是返回所有行的匹配;請參閱下面的perl命令以獲取解決方案。


通過Sobrique的評論choroba的回答啓發,這裏是上面的grep命令perl相當於

$ perl -lne 'print for m/\b(\d+) guys\b/g' <<<"365 guys or 366 guys, but not foo12 guys." 
365 
366 

簡單地忽略g只匹配最多號每行。

0

標準sed正則表達式,你可以從貪婪的比賽中受益,如果你扭轉字符串匹配

echo ... | rev | sed -E 's/.*syug ([0-9]+).*/\1/g' | rev 

顯然這是一個黑客,但絕望的時候...

1

在bash:

$ s="A number is about to show up 1 and now I want to parse 365 guys and some extra junk" 
$ [[ $s =~ ([0-9]+)\ +guys.*$ ]] && echo ${BASH_REMATCH[1]} 
365 

或者使用awk:

$ echo "$s" | awk '/guys/{for (i=1;i<=NF;i++) if ($i=="guys" && $(i-1)+0==$(i-1)) print $(i-1)}' 
365 
0

@Andrew卡西迪:@try:

echo "A number is about to show up 1 and now I want to parse 365 guys and some extra junk" | 
awk '/guys/{print VAL;exit} {VAL=$0}' RS=" " 
0

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

sed -r 's/.*\b([0-9]+) guys.*/\1/' file 

或者是:

sed -r 's/.*\<([0-9]+) guys.*/\1/' file 

製作模式的數字部分匹配一個單詞邊界。