我试图使用sed来清理url行来提取域。

所以从:

http://www.suepearson.co.uk/product/174/71/3816/

我想要:

http://www.suepearson.co.uk/

(不管后面有没有斜杠,都没有关系)

我试过:

 sed 's|\(http:\/\/.*?\/\).*|\1|'

And(转义非贪婪量词)

sed 's|\(http:\/\/.*\?\/\).*|\1|'

但我似乎不能让非贪婪量词(?)工作,所以它总是匹配整个字符串。


当前回答

您还应该考虑没有匹配界限的情况。你是否想输出这一行。如果不匹配,我这里的示例不会输出任何内容。

你需要前缀到第三个/,所以选择两次字符串的任何长度不包含/和后面的/,然后字符串的任何长度不包含/,然后匹配/后面的任何字符串,然后打印选择。这个想法适用于任何单个的char delims。

echo http://www.suepearson.co.uk/product/174/71/3816/ | \
  sed -nr 's,(([^/]*/){2}[^/]*)/.*,\1,p'

使用sed命令,您可以快速删除前缀或delim选择,如:

echo 'aaa @cee: { "foo":" @cee: " }' | \
  sed -r 't x;s/ @cee: /\n/;D;:x'

这比一次吃焦肉快多了。

如果之前匹配成功,跳转到标签。在第一道线/之前加\n。移除到第一个\n。如果添加了\n,则跳转到结束并打印。

如果有开始和结束delim,很容易删除结束delim,直到你到达你想要的第n -2个元素,然后做D技巧,在结束delim后删除,如果不匹配跳转到删除,在开始delim和打印之前删除。这仅在开始/结束分隔成对出现时有效。

echo 'foobar start block #1 end barfoo start block #2 end bazfoo start block #3 end goo start block #4 end faa' | \
  sed -r 't x;s/end//;s/end/\n/;D;:x;s/(end).*/\1/;T y;s/.*(start)/\1/;p;:y;d'

其他回答

@Daniel H(关于你对andcoz的回答的评论,虽然是很久以前的事了):删除后面的零

s,([[:digit:]]\.[[:digit:]]*[1-9])[0]*$,\1,g

这是关于清楚地定义匹配条件……

以下是你可以用两步方法和awk完成的事情:

A=http://www.suepearson.co.uk/product/174/71/3816/  
echo $A|awk '  
{  
  var=gensub(///,"||",3,$0) ;  
  sub(/\|\|.*/,"",var);  
  print var  
}'  

输出: http://www.suepearson.co.uk

希望有帮助!

如果你有gnu grep,那么可以使用perl regex:

grep -Po '^https?://([^/]+)(?=)' <<< 'http://www.suepearson.co.uk/product/174/71/3816/'
http://www.suepearson.co.uk

或者,在域名使用后获取一切

grep -Po '^https?://([^/]+)\K.*' <<< 'http://www.suepearson.co.uk/product/174/71/3816/'
/product/174/71/3816/
sed 's|(http:\/\/[^\/]+\/).*|\1|'

克利斯朵夫·西格哈特(Christoph Sieghart)著

在sed中获得非贪婪匹配的技巧是匹配除终止匹配的字符外的所有字符。我知道,这很简单,但我在这上面浪费了宝贵的时间,毕竟shell脚本应该是快速而简单的。所以以防别人需要

贪婪匹配

% echo "<b>foo</b>bar" | sed 's/<.*>//g'
bar

非贪婪匹配

% echo "<b>foo</b>bar" | sed 's/<[^>]*>//g'
foobar