使用sed替换不在行尾的模式

时间:2016-02-14 13:03:29

标签: regex sed

假设我已输入:

/a/b/c/d/e/
/a/b/c/d/e
a/b/c/d/e/
a/b/c/d/e

我想用/替换不在边缘的所有+,因此输出为:

/a+b+c+d+e/
/a+b+c+d+e
a+b+c+d+e/
a+b+c+d+e

我试过这个命令:

sed -e "s#\(.\)/\(.\)#\1+\2#g"

虽然接近但不完全:

/a+b/c+d/e/
/a+b/c+d/e
a+b/c+d/e/
a+b/c+d/e

可能是因为\(.\)个字符之间的/重叠。

我不相信sed在行的开头或结尾有一个空匹配运算符。那么,这是怎么做到的?

5 个答案:

答案 0 :(得分:2)

您可以将所有斜杠翻译为+,然后用斜杠替换+(在开头或结尾):

sed 'y/\//+/;s/^+\|+$/\//g;'

或者如果OR运算符不可用:

sed 'y/\//+/;s/^+/\//;s/+$/\//;'

如果更改分隔符以避免转义所有文字斜杠,则更好:

sed 'y~/~+~;s~^+\|+$~/~g;'

或者如果OR运算符不可用:

sed 'y~/~+~;s~^+~/~;s~+$~/~;'

(其中^是该行开头的锚点,而$是该行的

其他方法:您可以使用占位符保护要保留的斜杠:

sed 's~^/~{`%{~;s~/$~{`%{~;y~/~+~;s~{`%{~/~g;'

答案 1 :(得分:1)

如果您有perl,可以使用以下内容:

perl -pe 's~(?<!^)/(?!$)~+~g' file

<强>输出:

/a+b+c+d+e/
/a+b+c+d+e
a+b+c+d+e/
a+b+c+d+e

否则你可以使用这个sed和2个替代品:

sed -r 's~(.)/(.)~\1+\2~g; s~(.)/(.)~\1+\2~g' file

或者这种标签和循环:

sed -r ':a;s|(.)/(.)|\1+\2|g;ta' file

答案 2 :(得分:0)

这是一个提供输出的sed命令:

sed -r 's=(.)/\b=\1+=g;' file
  • 通常/用作s命令的分隔符,但在这里我们使用=
  • /匹配前面有某些内容(.)并且我们处于单词边界
  • 最初我尝试了(.)/(.),但这不起作用:
    • 消耗了第二个点,下一个匹配仅在它之后开始,
    • 即。在x/y/<中,第二场比赛只会看到/z而不是y/z
    • \b第一场比赛不会消耗y而第二场比赛会看到y/

答案 3 :(得分:0)

这是做这样的工作的常用且非常有用的sed习语:

$ sed 's:a:aA:g; s:^/\|/$:aB:g; s:/:+:g; s:aB:/:g; s:aA:a:g' file
/a+b+c+d+e/
/a+b+c+d+e
a+b+c+d+e/
a+b+c+d+e

第一个子项将所有a更改为aA。此时输入中没有字母a,后面没有字母A(我们需要先执行此操作,以确保在我们的第二个子字母后面只有aB个输入是第二个子结果的结果

第二个子项将行的开头或结尾处的所有/更改为aB。此时,输入中唯一的aB s位于行的开头或结尾处最初为/的位置。

第3个子项将所有剩余的/(即不在行的开头或结尾的那些)更改为+

第4个子点将aB恢复为原始前/后/

第5个子点将aA恢复为原始a

答案 4 :(得分:0)

这可能适合你(GNU sed):

sed ':a;s/\([^\/]\)\/\([^\/]\)/\1+\2/g;ta' file

或者视觉上更容易:

sed -r ':a;s#([^/])/([^/])#\1+\2#g;ta' file

两次真正的regexp相同:

sed 's/\([^\/]\)\/\([^\/]\)/\1+\2/g;s/\([^\/]\)\/\([^\/]\)/\1+\2/g' file