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

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


当前回答

这是如何使用sed健壮地进行多字符字符串的非贪婪匹配。假设你想改变每一个foo…Bar to <foo…Bar >,例如这个输入:

$ cat file
ABC foo DEF bar GHI foo KLM bar NOP foo QRS bar TUV

应该变成这样的输出:

ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

要做到这一点,你将foo和bar转换为单独的字符,然后在它们之间使用这些字符的反字符:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/g; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC <foo DEF bar> GHI <foo KLM bar> NOP <foo QRS bar> TUV

在上述:

/ / @ @A / g;s / {/ @B / g;s/}/@C/g正在将{和}转换为输入中不存在的占位符字符串,这样这些字符就可以转换为foo和bar。 s / foo / {/ g;S /bar/}/g将foo和bar分别转换为{和} S /{[^{}]*}/<&>/g正在执行我们想要的操作-将foo…Bar到<foo…Bar > s /} /酒吧/ g;S /{/foo/g将{和}转换回foo和bar。 s / @C /} / g;s / @B / {/ g;s/@ a /@/g将占位符字符串转换回原始字符。

请注意,上面的方法并不依赖于输入中不存在的任何特定字符串,因为它在第一步中就制造了这样的字符串,它也不关心你想要匹配的任何特定regexp的哪个出现,因为你可以在表达式中使用{[^{}]*}尽可能多的次数来隔离你想要的实际匹配和/或使用seds数值匹配操作符,例如只替换第二个出现:

$ sed 's/@/@A/g; s/{/@B/g; s/}/@C/g; s/foo/{/g; s/bar/}/g; s/{[^{}]*}/<&>/2; s/}/bar/g; s/{/foo/g; s/@C/}/g; s/@B/{/g; s/@A/@/g' file
ABC foo DEF bar GHI <foo KLM bar> NOP foo QRS bar TUV

其他回答

以下是你可以用两步方法和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

希望有帮助!

还没有看到这个答案,所以这里是如何用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正则表达式了。

由于这里也标记了PCRE,我们可以通过在regex中使用非惰性匹配来使用GNU grep。它将匹配与。*相对的第一个最近的匹配(它实际上是贪婪的,直到匹配的最后一次出现)。

grep -oP '^http[s]?:\/\/.*?/' Input_file

解释:此处使用grep的oP选项,其中-P负责启用PCRE正则表达式。在grep的主程序中提到regex,它匹配开始http/https,后面跟着://直到下一次出现/,因为我们已经使用了。*?它将查找first / after (http/https://).它只打印匹配的部分。

Sed不支持“非贪婪”操作符。

你必须使用“[]”操作符来排除“/”匹配。

sed 's,\(http://[^/]*\)/.*,\1,'

附注:不需要反斜杠"/"。

如果你有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/