如何修剪线条包括带有sed的特定字符串

时间:2014-08-20 00:01:21

标签: regex linux

我有单独的文件包含每个类似的路径字符串;

path = /aaa/bbb/ccc.com/user@ccc.com/dddd/user@yahoo.com/
path = /aaa/bbb/ccc.com/user@ccc.com/dddd/user@hotmail.co.uk/
path = /aaa/bbb/ccc.com/user@ccc.com/dddd/user@abc.xxx.co.uk/
path = /aaa/bbb/ccc.com/user@ccc.com/dddd/user55@ccc.com/

我想修剪线条像;

path = /aaa/bbb/ccc.com/user/dddd/.user@yahoo/
path = /aaa/bbb/ccc.com/user/dddd/.user@hotmail/
path = /aaa/bbb/ccc.com/user/dddd/.user@abc/
path = /aaa/bbb/ccc.com/user/dddd/.user55@ccc.com/

我几乎可以在下面实现(所有字符串都在单独的文件中但在第15行)

sed -r '15s!@[^/]+(/[^/]+/[^.@]+@[^.]+).*$!\1/!g' $file

然而,我有一个问题,点部分削减它;

path = /aaa/bbb/ccc.com/user/dddd/user55@ccc/
相反,应该是;

path = /aaa/bbb/ccc.com/user/dddd/.user55@ccc/

提前致谢,

2 个答案:

答案 0 :(得分:0)

您必须使用两个匹配项:

sed -E 's/(.*?\..*?)\/(.*?)@\1/\1\/\2/g'
  • 正则表达式:(.*?\..*?)\/(.*?)@\1
  • 替换:\1\/\2
  • 标志:g(全球)

结果:

path = /aaa/bbb/ccc.com/user/dddd/user@yahoo.com/
path = /aaa/bbb/ccc.com/user/dddd/user@hotmail.co.uk/
path = /aaa/bbb/ccc.com/user/dddd/user@abc.xxx.co.uk/
path = /aaa/bbb/ccc.com/user/dddd/user55@ccc.com/

sed -E 's/(\w+@\w+)[\w\.]*/\1/g'
  • 正则表达式:(\w+@\w+)[\w\.]*
  • 替换:\1
  • 标志:g(全球)

结果:

path = /aaa/bbb/ccc.com/user/dddd/user@yahoo/
path = /aaa/bbb/ccc.com/user/dddd/user@hotmail/
path = /aaa/bbb/ccc.com/user/dddd/user@abc/
path = /aaa/bbb/ccc.com/user/dddd/user55@ccc/

如果您的版本上没有-E开关,则可能必须使用

示例:

perl -pe 's/(.*?\..*?)\/(.*?)@\1/\1\/\2/g' -i filename.ext

如果我在bash中尝试这个,我得到以下结果:

root@home [~]# echo "path = /aaa/bbb/ccc.com/user@ccc.com/dddd/user55/" | sed -E 's/(.*?\..*?)\/(.*?)@\1/\1\/\2/g'
path = /aaa/bbb/ccc.com/user/dddd/user55/
root@home [~]# echo "path = /aaa/bbb/ccc.com/user/dddd/user55/" | sed -E 's/(\w+@\w+)[\w\.]*/\1/g'
path = /aaa/bbb/ccc.com/user/dddd/user55/

答案 1 :(得分:0)

使用具有三个捕获组的模式应该可以满足您的需要。第一组将捕获初始@后面的部分(作为我们从替换中省略的组),第二组将包含/dddd/部分,第三组将包含完整的user@somewhere使用前置.

's!(@.+\..+)(/.+/)(.+@.+)!\2.\3!g'

根据您的bash版本,您可以像这样使用它:

sed -i.bak -r 's!(@.+\..+)(/.+/)(.+@.+)!\2.\3!g' $file

(GNU bash,版本4.1.2(1)-release(x86_64-redhat-linux-gnu)

sed -i bak -E 's!(@.+\..+)(/.+/)(.+@.+)!\2.\3!g' $file

GNU bash,版本3.2.48(1)-release(x86_64-apple-darwin12)

结果:

path = /aaa/bbb/ccc.com/user/dddd/.user@yahoo.com/
path = /aaa/bbb/ccc.com/user/dddd/.user@hotmail.co.uk/
path = /aaa/bbb/ccc.com/user/dddd/.user@abc.xxx.co.uk/
path = /aaa/bbb/ccc.com/user/dddd/.user55@ccc.com/

如果你想在最后一场比赛结束时保持完整的分机,有点不清楚;如果不是sed可能不是最好的选择,因为它不能做任何前瞻,后视断言,也不能以任何直截了当的方式切换贪婪。如果这是一个交易破坏者,你可以在许多其他途径之一使用这种模式:

(@.+\..+)(/.+/)(.+@.+?)(\..*/)

结果:

path = /aaa/bbb/ccc.com/user/dddd/.user@yahoo
path = /aaa/bbb/ccc.com/user/dddd/.user@hotmail
path = /aaa/bbb/ccc.com/user/dddd/.user@abc
path = /aaa/bbb/ccc.com/user/dddd/.user55@ccc