2017-04-22 41 views
1

我使用這個命令行得到了包含各種其它標記的HTML文件中的特定行,鏈接等:如何將一個模式的最後出現匹配一行字符串

cat index.html | grep -m1 -oE '<a href="(.*?)" rel="sample"[\S\s]*.*</dd>' 

它輸出,我想這行:

<a href="http://example.com/something/one/" rel="sample" >Foo</a> <a href="http://example.com/something/two/" rel="sample" >Bar</a></dd> 

但我想只捕獲something/two(的最後 URL路徑),考慮到:

  • 事先不知道URL(這是一個處理多個html文件的腳本)
  • 該行有時可能只包含一個URL,

    <a href="http://example.com/something/one/" rel="sample" >Foo</a></dd> 
    

    在這種情況下,我想只有something/one獲得儘可能在這種情況下,最後之一。

我該怎麼做?

+0

如果某個'a'標籤被換行符打斷,那麼它會在兩個連續的行上同時出現? – RomanPerekhrest

+0

@RomanPerekhrest是不是'[\ S \ s] *'掩飾? – george

+0

不,我想,他想要定義一行中有多少個網址。如果存在多個URL - 捕獲查詢字符串,如果一行只包含一個url - 只捕獲查詢字符串的最後一部分,即'/ one /' – RomanPerekhrest

回答

1

如果你可以使用perl,然後在正則表達式中捕獲使得這更容易。

perl -ne 'm(.*<a href="[^:]+://[^/]*/(.*?)" rel="sample".*</dd>) and print "$1\n";' 

正則表達式基本上和grep一樣。我使用m()而不是//來避免在正則表達式中轉義/

初始的.*會貪婪地捕捉行開頭的所有內容。如果一條線上有多個鏈接,它將捕獲除最後一個以外的所有鏈接。這也適用於grep,但它會導致grep -o輸出行的開始,因爲它現在匹配正則表達式。

這與捕獲括號無關,因爲只有(.*?)內部的部分被捕獲和打印。

它將以與grep相同的方式使用。

cat index.html | perl -ne 'm(.*<a href="[^:]+://[^/]*/(.*?)" rel="sample".*</dd>) and print "$1\n";' 

or 

perl -ne 'm(.*<a href="[^:]+://[^/]*/(.*?)" rel="sample".*</dd>) and print "$1\n";' index.html 
2

只需添加

| grep -o 'href="[^"]*' | tail -n1 

第一部分只提取href秒,第二部分只保留最後一行。

如果你想只提取的路徑,你可以使用cut用分隔符設置爲/並提取了從第四列開始:

| grep -o 'href="[^"]*' | tail -n1 | cut -f4- -d/ 

因爲

href="http://example.com/something/two/ 
1   23   4   5 
1

在Linux中,GNU grep-P選項允許一個簡潔的解決方案:

$ grep -oP '.*<a href="http://.+?/\K[^"]+(?=/"\s*rel="sample".*</dd>$)' index.html 
something/two 

-o僅輸出匹配的部分(一個或多個),每個匹配線的

-P激活支持PRCEs (Perl-compatible Regular Expressions),它支持先進的正則表達式的構建體,例如非貪婪匹配(*?),滴到目前爲止的所有(\K)匹配,並且先行斷言((?=...)。

  • \K組合和(?=...)允許約束正則表達式到子表達式的興趣的匹配部分。
    注意沒有grep實現支持捕捉組,但上面的,這要歸功於-P啓用的功能,是提取捕獲組值的仿真。

至於你試過

  • -m1限制匹配 1的數,但-o也存在,對1的比賽仍然是全部印。

    • 此外,雖然你可以使用(...)優先,並不構成捕獲組grep,因爲有grep提取捕獲組值不支持。
  • 即使-E擴展正則表達式支持,先進的結構,如非貪婪匹配(.*?)是支持

相關問題