如何从半随机字符串中提取/解析完整的URL?


12

我想让bash从随机短字符串中解析/提取完整的URL(仅URL)。

例子:

bob, the address is http://www.google.com

要么

https://foo.com/category/example.html is up

要么

Error 123 occurred at http://bit.ly/~1223456677878

要么

Stats are up: https://foo1234.net/report.jpg

我尝试使用,cat foo_output | egrep -o "https?://[\w'-\.]*\s"但是似乎没有用。


听起来很恐怖,具体取决于您要对提取的URL进行处理...
vonbrand 2014年

Answers:


24

你试过了吗:

egrep -o 'https?://[^ ]+' foo_output

代替?

请注意,任何具有字符类的东西都被当作文字,因此说[\w]词character不匹配。此外,您无需在字符类中转义正则表达式元字符,即,说[\.]的与不太相同[.]


2
[^ ]太宽,你会想排除其他空白,(),可能昏迷,并且未在网址中不允许的所有字符。
斯特凡Chazelas

@StephaneChazelas你是对的。但是,我假设 URL前后都有一个空格,除非在行的开头或结尾。
devnull 2014年

5

当以自然语言嵌入URI时,URI不适合进行正则表达式匹配。但是,当前最先进的技术是John Gruber的“ 改进的自由,准确的正则表达式模式用于匹配URL”。当前发布的单行版本如下:

(?i)\b((?:[a-z][\w-]+:(?:/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))

尽管他的博客条目在解释他的测试语料库和正则表达式模式的局限性方面做得更好,但John似乎在这里也保持了要点。

如果要从命令行实现表达式,可能会发现自己受到所使用的正则表达式引擎或shell引用问题的限制。我发现Ruby脚本是最好的选择,但是您的工作量可能会有所不同。


2
请在回答中包括正则表达式,而不要链接到它。
terdon

@terdon,完整的正则表达式大约有60行。
vonbrand 2014年

2
@vonbrand我知道,我看到了。我们只是倾向于避免链接到外部资源。SE网站的重点是成为Wiki。如果您链接的博客离线了怎么办?您的答案将变得毫无用处。无论如何,60行并不算多,可读性仅为60行。
terdon

2

匹配URL的问题在于URL中几乎可以包含任何内容

https://encrypted.google.com/search?hl=en&q=foo#hl=en&q=foo&tbs=qdr:w,sbd:1

正如你所看到的,上面的(有效)URL包含$?#&,.:。基本上,可以确定URL不包含空格的唯一内容是空格。考虑到这一点,您可以使用以下简单的模式提取URL:

$ grep -oP 'http.?://\S+' file 
http://www.google.com
https://foo.com/category/example.html
http://bit.ly/~1223456677878
https://foo1234.net/report.jpg

\S任何相匹配的非空间在Perl兼容正则表达式(PCREs)字符,则-P激活用于PCREs grep-o使得它仅打印该行的匹配的段。


0

我会去链接,但有所不同。如果在名为strings.txt的文本文件中有类似您的文本片段,则可以执行以下操作:

grep http ./strings.txt | sed 's/http/\nhttp/g' | grep ^http | sed 's/\(^http[^ <]*\)\(.*\)/\1/g' | grep IWANTthis | sort -u

说明:

grep http ./st3.txt      => will catch lines with http from text file
sed 's/http/\nhttp/g'    => will insert newline before each http
grep ^http               => will take only lines starting with http
sed 's/\(^http[^ <]*\)\(.*\)/\1/g'   
                         => will preserve string from ^http until first space or < (the latter in hope if 
grep IWANTthis           => will take only urls containing your text of your interest; you can omit this.
sort -u                  => will sort the list and remove duplicates from it 

由于网址可能无法正常工作,您可以使用您感兴趣的网址进行其他错误检查。例如wget -p URL -O /dev/null-如果URL不可用,它将打印完全不同的错误代码,因此您可以设置一个循环来处理链接列表并输出其有效性状态。

如果最终要从html文件中提取链接,则sed在特殊情况下可能会遇到一些麻烦。正如在一个有趣的(帖子)中所建议的那样,您可能已经看过了-最好不要使用regexps而是html解析器引擎。一种此类易于使用的解析器是纯文本浏览器lynx(可在任何Linux上使用)。这使您可以立即转储文件中所有链接的列表,然后只需使用grep提取所需的URL。

lynx -dump -listonly myhtmlfile.html | grep IWANTthisString | sort -u

但是,这不适用于大多数损坏的html文件或带有链接的文本片段。



-1
cat text-file.txt | grep -Eo '(https?|ftp|file)://[-A-Za-z0-9\+&@#/%?=~_|!:,.;]*[-A-Za-z0-9\+&@#/%=~_|]'

或者,附加SED命令以将其存储到CSV文件中:

| sed 's/;/<tab>/g' > file.csv
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.