2012-03-15 71 views
3

我有以下內容的HTML頁面,停止貪婪:如何用grep從慶典

[...] 
<tr><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr> 
<tr><td class="n"><a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td></tr> 
<tr><td class="n"><a href="play-1.0.2.zip">play-1.0.2.zip</a></td></tr> 
[...] 

而且我想只提取

play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 

到隨後找到最新版本(在這種情況下,將play-1.0.2.1.zip)

所以我試圖用

cat tmp.html | grep "<a href=\".*\"" 

<a href="play-1.0.1.zip">play-1.0.1.zip</a></td><td class="m" 
<a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td><td class="m" 
<a href="play-1.0.2.zip">play-1.0.2.zip</a></td><td class="m" 

於是,我就懶:

cat tmp.html | grep "<a href=\".*?\"" 

和否定報價

cat tmp.html | grep "<a href=\"[^\"]*?\"" 

他們兩個返回沒什麼

我需要只匹配的部分(而不是href),然後找到最新的,但我stu CK這個貪婪的問題...

-

非常感謝所有的答案,他們都非常有用,這是很難決定哪一個是正確的,到最後我已經解決了它與:

grep -v '.*-RC.*' index.html | grep -oP 'play-1.*?.zip' | sort -Vru | head -1 
+1

的grep -E 「 strkol 2012-03-15 13:08:56

+1

有沒有必要使用'cat tmp.html'與grep因爲grep可以處理它自己的文件。你應該使用'grep -E pattern tmp.html'。 – piotrekkr 2012-03-15 13:17:06

回答

6

相反,其他的答案,這可以完全使用grep完成。

您的輸出與您的輸入略有不同 - 還有額外的元素顯示。對於這個答案的目的,我將使用這個文件:

<tr><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr> 
<tr><td class="n"><a href="play-1.0.2.1.zip">play-1.0.2.1.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr> 
<tr><td class="n"><a href="play-1.0.2.zip">play-1.0.2.zip</a></td><td class="n"><a href="play-1.0.1.zip">play-1.0.1.zip</a></td></tr> 

有你需要做的幾件事情。首先,你需要設置正確的grep開關。您需要:

  • -o只輸出每行
  • -P使用Perl兼容的正則表達式引擎

現在你可以使用的匹配部分?改性劑,以防止貪婪匹配:

grep -o -P '<a href=".*?"' test.html 

<a href="play-1.0.1.zip" 
<a href="play-1.0.1.zip" 
<a href="play-1.0.2.1.zip" 
<a href="play-1.0.1.zip" 
<a href="play-1.0.2.zip" 
<a href="play-1.0.1.zip" 

這是不完全正確,因此我們將錨正則表達式來該行的第一場比賽:

grep -o -P '^<tr><td class="n"><a href=".*?"' test.html 

<tr><td class="n"><a href="play-1.0.1.zip" 
<tr><td class="n"><a href="play-1.0.2.1.zip" 
<tr><td class="n"><a href="play-1.0.2.zip" 

這纔是正確的,但有太多的克魯夫特。我們需要使用的是零寬度斷言(PCRE語法的一部分)。基本上不包括匹配模式的正則表達式位。

grep -o -P '(?<=^<tr><td class="n"><a href=").*?(?=")' test.html 

play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 

現在你可以做任何你需要的排序列表。零所寬度斷言的更多信息可以在這裏找到:http://www.regular-expressions.info/lookaround.html

+0

+1好的答案,以顯示你如何迭代到正則表達式。 – 2012-03-15 13:51:08

2

嘗試與-E開關:

[email protected]:~$ echo '<a href="play-1.0.1.zip">play-1.0.1.zip</a></td>' | grep -E '<a href=".*?"' 
<a href="play-1.0.1.zip">play-1.0.1.zip</a></td> 
+1

這是有效的,因爲默認情況下,grep使用基本的正則表達式引擎。 '-E','-F'和'-P'開關會改變使用的引擎。有關更多詳細信息,請參閱手冊頁。 – 2012-03-15 13:16:40

1

grep似乎不喜歡這樣做的正確的工具,因爲你要解開一個子匹配。

這裏有一個Perl的一行,將做到這一點,但:

$ perl -ne 'while(/<a href="([^"]+)"/g){print $1, "\n";}' input 
play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 
3
$ grep 'href=' tmp.html | sed 's/.*href="\(.*\)".*/\1/' 
play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 
+0

好吧......終於有了'sed'解決方案:)...那麼這似乎不工作,如果該文件包含其他行,所以在'grep'後面管這個? – 2012-03-15 13:23:11

+0

是的,正確的,修復它,仍然是最短的解決方案呢:-) – strkol 2012-03-15 13:28:37

5

隨着GNU工具,你可以做

grep -oP '(?<=<td class="n"><a href=")[^"]+' | sort -Vr | head -1 
0

AWK是一個偉大的工具,如果你知道的場數:

awk -F\" '$4 ~ /play.*zip/{ print $4 }' 

或者這是一種混亂的方式;搜索所有zip文件:

cat file | tr '"' '\n' | grep -e '.zip$' | sort -u 

這將爲您獲取所有zip文件。 tr實用程序使用不足,它只是替換字符,在這種情況下,用換行符替換每個雙引號,很好地在自己的行中獲取引用的數據,您可以在其中查找它。排序-u避免了dups。

0

一個Perl方式:

cat thefile | perl -anF'"' -e 'print $F[3],"\n";($v)=$F[3]=~/(\d.*\d)/;$m=$v if$v gt $m;}{print "max=$m\n";' 

輸出:

play-1.0.1.zip 
play-1.0.2.1.zip 
play-1.0.2.zip 
max=1.0.2.1 
1

使用克雷格·安德魯斯通過添加OSX支持提供了答案。

grep -o -P '(?<=^<tr><td class="n"><a href=").*?(?=")' /test.html | sort -n -r -k1.10,12 

結果:

play-1.0.2.1.zip 
play-1.0.2.zip 
play-1.0.1.zip 
+0

就像爲那些僅限OS x的用戶添加了幫助一樣。排序-V在OSX中默認不可用。這也應該適用於其他基於UNIX的機器。 – E1Suave 2012-04-18 19:52:27

3

沒看到切割(我喜歡它的簡潔&速度),因此:

切-d \」 -F4 TMP。 html | sort -Vu | tail -1

輸出:

play-1.0.2.1.zip