我正在使用此命令行从包含各种其他标签,链接等的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
(最后网址的路径),考虑到:
该行有时只能包含1个URL,例如
<a href="http://example.com/something/one/" rel="sample" >Foo</a></dd>
在这种情况下,我希望只获得something/one
,因为在这种情况下它是最后一个。
我该怎么做?
答案 0 :(得分:2)
添加
| grep -o 'href="[^"]*' | tail -n1
第一部分仅提取href
s,第二部分仅保留最后一行。
如果您只想提取路径,可以使用cut
并将分隔符设置为/
,并从第四列开始提取所有内容:
| grep -o 'href="[^"]*' | tail -n1 | cut -f4- -d/
,因为
href="http://example.com/something/two/
1 23 4 5
答案 1 :(得分: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 :(得分:1)
在Linux上,GNU grep
的{{1}}选项可以提供简洁的解决方案:
-P
$ grep -oP '.*<a href="http://.+?/\K[^"]+(?=/"\s*rel="sample".*</dd>$)' index.html
something/two
仅输出匹配的每一行的匹配部分。
-o
激活对PRCEs (Perl-compatible Regular Expressions)的支持,{{3}}支持高级正则表达式构造,例如非贪婪匹配(-P
),删除到目前为止匹配的所有内容(*?
),以及预见断言(\K
)。
(?=...
和\K
的组合允许将正则表达式的匹配部分约束到感兴趣的子表达式。(?=...)
实现支持捕获组,但由于grep
启用的功能,上述内容是提取单个的模拟捕获组值。至于您尝试的内容:
-P
将匹配的行的数量限制为1,但如果-m1
也存在,则多个匹配 on <1> 仍然全部打印。
-o
用于优先级,但这并不构成(...)
中的捕获组,因为它有不支持在grep
中提取捕获组值。即使grep
支持扩展正则表达式支持,非贪婪匹配(-E
)等高级构造也不支持