使用 sed 从包含多个 URL 的文本中提取 URL

使用 sed 从包含多个 URL 的文本中提取 URL

我有一个包含文本和多个 URL 的字符串。如何使用 sed 提取一个特定 URL(特定域的 URL)?例如,我有这个:

Text foo bar Text foo bar <br /><br /> http://www.this.file <br />http://another.file <br />http://mine.com/this.html <br />http://myURL.net/files/IWANTthis <br />http://www.google.com/thisnot

sed应返回以下内容: http://myURL.net/files/IWANTthis

答案1

在特殊情况下,sed 可能会出现一些问题。正如许多地方所建议的那样(例如)- 不使用正则表达式,而是使用 html 解析器引擎。纯文本浏览器 lynx(可在任何 Linux 上使用)中包含一个此类易用的解析器。然后,您只需使用 grep 提取所需的 URL。

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

但是,这不适用于损坏的 html 文件(无法正确解析)或带有链接的文本片段。另一种简单的方法是链接。如果您在名为 st3.txt 的文本文件中有一个类似的文本片段,您可以执行以下操作:

grep http ./st3.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 <
grep IWANTthis           => will take only urls containing your text of interest
sort -u                  => will sort and remove duplicates from your list

答案2

您可以使用grep扩展正则表达式(正则表达式)为此:

grep -Eo '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?' <<< '<input_string>'

命令各部分和正则表达式的解释:

  • grep -Eo:我们有grep两个选择。
    • -E: 使能够POSIX 扩展正则表达式。
    • -o:仅打印每行匹配的部分(若没有此选项,则grep默认打印包含匹配部分的整行)。
  • '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?':此正则表达式可能比您需要的更复杂一些,因此您应该简化或删除不必要的复杂部分。(复杂性是尝试提供通用解决方案的结果。)
    • ([-+.[:alnum:]]+://)?:这符合方案URL 的末尾。?末尾的指定匹配一次或根本不匹配(因此myURL.net即使没有预先添加方案也会匹配)。我们包含略微不寻常的字符是-+.因为RFC 3986指定“方案名称由以字母开头的字符序列组成,后跟字母、数字的任意组合,加号 ('+')、句号 ('.') 或连字符 ('-')“(重点是我的)。如果你确定总是http://会出现在前面myURL.net,那么你可以用简单的替换正则表达式的这一部分http://
    • ([-[:alnum:]]+.)*:这匹配子域名*末尾的 指定匹配零次或多次(以便匹配像a.b.in 这样的子域a.b.myURL.net)。我们包含连字符 ( -),因为RFC 1035指定“[子域标签] 必须以字母开头,以字母或数字结尾,并且内部字符只能为字母、数字和连字符“(重点是我的)。如果您确定不需要匹配子域,那么您可以删除正则表达式的这一部分。
    • myURL.net:这是文字字符串的直接匹配myURL.net
    • (:[[:digit:]]+)?:这匹配任何端口指定如果它包含在 URL 中。
    • (/[[:graph:]]*)?:这与 URL 的其余部分匹配。[:graph:]匹配任何可见字符。
  • <<< '<input_string>':我们grep使用一个这里是字符串. (echo '<input_string>' |是常见的选择。)

例子:

$ grep -Eo '([-+.[:alnum:]]+://)?([-[:alnum:]]+.)*myURL.net(:[[:digit:]]+)?(/[[:graph:]]*)?' <<< 'Text foo bar Text foo bar <br /><br /> http://www.this.file <br />http://another.file <br />http://mine.com/this.html <br />http://myURL.net/files/IWANTthis <br />http://www.google.com/thisnot'
http://myURL.net/files/IWANTthis

再次强调,我上面给出的正则表达式可能过于复杂,无法满足您的需要。您应该根据自己的目的进行修改。下面这样简单的操作就可以了:

grep -Eo 'http://myURL.net(/[[:graph:]]*)?' <<< '<input_string>'

答案3

您可以使用:sed 's/<br\ *\/>/\n/g' html_file | grep myURL.net

输出:http://myURL.net/files/IWANTthis

基本上,我用<br />换行符替换所有内容,然后用 grep 抓取相关行。

这并没有考虑到<br>标签的所有可能的(html 允许的)变化,但它可以处理示例中的变化。

答案4

您可以使用 来解析文件中所有的 URL,sed然后grep查找匹配项。

sed "s/http/\nhttp/g" your.html | sed -n "s#\(.*\)\(http.*//[a-Z0-9./-]*[^a-Z/]\)\(.*\)#\2#p;" | grep IWANTthis

在第一遍中,sed用前面的换行符替换所有 http,以便sed在第二遍中更容易地sed提取 URL。这个正则表达式通常对我有用,但您可能需要对其进行调整以满足您的需求。

注意:您可以一次性完成此操作,但由于神秘性较强,很少使用的sed命令可能难以维护,因此会变得复杂。

相关内容