2009-06-12 84 views
0

我有一個HTML文件,並且想要提取<li></li>之間的文本標籤。當然也有一百萬的方式做到這一點,但我想這將是獲得有用的多爲簡單的shell命令這樣的習慣:awk/etc:從文件中提取匹配

awk '/<li[^>]+><a[^>]+>([^>]+)<\/a>/m' cities.html 

的問題是,這個打印一切而我只是想在括號中打印匹配 - ([^>]+) - awk不支持這個,或者我無能。後者似乎更有可能。如果您想將提供的正則表達式應用於文件並僅提取指定的匹配項,那麼您將如何執行?我已經知道了其他六種方式,但我不想讓awk贏得這一輪;)

編輯:數據結構不好,所以使用位置匹配($1, $2, etc.)是一個不行。

回答

0

通過腳本,如果你能得到你想要的(這意味着<li><a>標籤是在一行。

$ cat test.html | awk 'sub(/<li[^>]*><a[^>]*>/,"")&&sub(/<\/a>.*/,"")' 

$ cat test.html | gawk '/<li[^>]*><a[^>]*>(.*?)<\/a>.*/&&$0=gensub(/<li[^>]*><a[^>]*>(.*?)<\/a>.*/,"\\1", 1)' 

第一個是爲每一個AWK,第二個是用於GNU AWK。

0

有幾個問題,我看到:

  • 圖案具有尾隨「M」,這是多行顯著在Perl比賽,但awk中不使用Perl兼容的正則表達式。 (至少,標準(非GNU)awk不)。
  • 忽略這一點,該模式似乎搜索後接錨點'<a>'到'</a>'的'開始列表項',而不是搜索結束列表項。
  • 您搜索任何不是'>'作爲錨的主體;這並不是自動錯誤,但可能更常見的是搜索任何不是'<'的東西,或者其他任何東西都不是。
  • Awk不會執行多行搜索。
  • 在Awk中,'$1'表示第一個字段,其中字段由字段分隔符字符分隔,默認爲空白。
  • 在經典nawk(如「sed & awk的書老式1991記載)沒有拉子場比賽進行的替代機制等

目前尚不清楚的是在awk是這個工作的正確工具。事實上,正則表達式是這項工作的正確工具並不完全清楚。

+0

至於你的第二點,是的,在我的描述和模式中,我有點矛盾。我可以向你保證模式完全符合我的要求。我並不知道awk沒有做多線。 也許它不是正確的工具;我可以在4行python中提取文本,只需使用一個命令方法就可以更方便地使用單個命令來提取它們並完成它。當然,我花了一個小時試圖找出這個命令,所以......;) – tdavis 2009-06-12 02:05:33

2

如果你想在一般情況下這樣做,你的列表標籤可以包含任何合法的HTML標記,那麼awk是錯誤的工具。這項工作的正確工具將是一個HTML解析器,您可以信任這個解析器來正確獲取HTML解析的所有小細節,包括HTML和格式錯誤的HTML的變體。

如果你正在做一個特殊情況,你可以控制HTML格式,那麼你可以使awk爲你工作。例如,我們假設您可以保證每個列表元素永遠不會佔用多行,總是以同一行上的</li>終止,從不包含任何標記(例如包含列表的列表),然後您可以使用awk做到這一點,但你需要編寫一個整體awk程序,首先查找包含列表元素的線條,然後使用其他awk命令找到剛纔子你感興趣的內容。

但總的來說,awk是錯誤的工具這個工作。

0

不知道awk,那麼Perl怎麼樣呢?

tr -d '\012' the.html | perl \ 
-e '$text = <>;' -e 'while (length($text) > 0)' \ 
-e '{ $text =~ /<li>(.*?)<\/li>(.*)/; $target = $1; $text = $2; print "$target\n" }' 

1)從文件中刪除新行,管通過的perl

2)初始化與完整的文本的變量,啓動一個循環,直到文本消失

3)做一個「非貪婪」匹配列表項標籤所限定的內容,保存並打印目標,設置爲下一步

有意義嗎? (警告,我自己沒有嘗試這個代碼,需要儘快回家......)

P.S. - 「perl -n」是Awk(nawk?)模式。 Perl在很大程度上是Awk的超集,所以我從來沒有去學習Awk。

+0

你回答的是這個問題所說的,而不是awk正則表達式所做的:D並且我懷疑腳本可能被壓縮 - 但是它是Perl和TMTWOTDI! – 2009-06-12 07:43:10

1
gawk -F'<li>' -v RS='</li>' 'RT{print $NF}' file 

對我來說工作得很好。