我试图使用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|'

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


当前回答

还没有看到这个答案,所以这里是如何用vi或vim做到这一点:

vi -c '%s/\(http:\/\/.\{-}\/\).*/\1/ge | wq' file &>/dev/null

这将全局运行vi:%s替换(后面的g),如果没有找到模式,则避免引发错误(e),然后将结果更改保存到磁盘并退出。&>/dev/null可以防止GUI在屏幕上短暂闪烁,这很烦人。

有时候我喜欢用vi来处理超级复杂的正则表达式,因为(1)perl已经奄奄一息了,(2)vim有一个非常先进的正则表达式引擎,(3)在我日常使用的编辑文档中,我已经非常熟悉vi正则表达式了。

其他回答

另一种方法,不使用正则表达式,是使用字段/分隔符方法,如

string="http://www.suepearson.co.uk/product/174/71/3816/"
echo $string | awk -F"/" '{print $1,$2,$3}' OFS="/"

因为您特别指出您正在尝试使用sed(而不是perl、cut等),所以请尝试分组。这就避免了非贪婪标识符可能无法被识别。第一组是协议(即协议)。'http://', 'https://', 'tcp://',等等)。第二组是域:

echo "http://www.suon.co.uk/product/1/7/3/" | sed "s|^\(.*//\)\([^/]*\).*$|\1\2|"

如果您不熟悉分组,请从这里开始。

使用sed,我通常通过搜索除分隔符以外的任何东西来实现非贪婪搜索,直到分隔符:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*\)/.*;\1;p'

输出:

http://www.suon.co.uk

这是:

don't output -n search, match pattern, replace and print s/<pattern>/<replace>/p use ; search command separator instead of / to make it easier to type so s;<pattern>;<replace>;p remember match between brackets \( ... \), later accessible with \1,\2... match http:// followed by anything in brackets [], [ab/] would mean either a or b or / first ^ in [] means not, so followed by anything but the thing in the [] so [^/] means anything except / character * is to repeat previous group so [^/]* means characters except /. so far sed -n 's;\(http://[^/]*\) means search and remember http://followed by any characters except / and remember what you've found we want to search untill the end of domain so stop on the next / so add another / at the end: sed -n 's;\(http://[^/]*\)/' but we want to match the rest of the line after the domain so add .* now the match remembered in group 1 (\1) is the domain so replace matched line with stuff saved in group \1 and print: sed -n 's;\(http://[^/]*\)/.*;\1;p'

如果你想在域名后面加上反斜杠,那么在组中再加一个反斜杠来记住:

echo "http://www.suon.co.uk/product/1/7/3/" | sed -n 's;\(http://[^/]*/\).*;\1;p'

输出:

http://www.suon.co.uk/

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

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

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

还没有看到这个答案,所以这里是如何用vi或vim做到这一点:

vi -c '%s/\(http:\/\/.\{-}\/\).*/\1/ge | wq' file &>/dev/null

这将全局运行vi:%s替换(后面的g),如果没有找到模式,则避免引发错误(e),然后将结果更改保存到磁盘并退出。&>/dev/null可以防止GUI在屏幕上短暂闪烁,这很烦人。

有时候我喜欢用vi来处理超级复杂的正则表达式,因为(1)perl已经奄奄一息了,(2)vim有一个非常先进的正则表达式引擎,(3)在我日常使用的编辑文档中,我已经非常熟悉vi正则表达式了。