我试图使用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
不幸的是,如前所述,sed不支持这一点。
为了克服这个问题,我建议使用次优方法(实际上甚至更好),使用类似vim sed的功能。
在.bash-profile中定义
vimdo() { vim $2 --not-a-term -c "$1" -es +"w >> /dev/stdout" -cq! ; }
这将创建无头vim来执行命令。
现在你可以这样做:
回声路径美元| vimdo“% s_ \ c: [a-zA-Z0-9 \ \ /] python (a-zA-Z0-9 \ {-} \\/]\{-}:__ g”,
过滤掉$PATH中的python。
使用-在vimdo中从管道中输入。
而大多数语法是相同的。Vim具有更高级的特性,并且使用\{-}是非贪婪匹配的标准。参见帮助regexp。