我试图编写一个 sed 命令,如果它发现一个冒号周围没有空格,它会在冒号前后各放一个空格,也就是说,abc:def
将转换为abc : def
.我正在这样做:
echo "abc:def" | sed -e 's/[^\s]\+:[^\s]\+/ : /g'
输出仍然是abc:def
,我该怎么做?我上面的命令有什么问题?
答案1
\s
表示空格sed
不可移植 - 例如在 POSIX 实现中,您的表达式将不匹配,例如(GNU sed,在 posix 模式下):
$ echo "abc:def" | sed --posix -e 's/[^\s]\+:[^\s]\+/ : /g'
abc:def
但是如果你的表情做过匹配,它不会做你想要的,因为它将替换整个序列,例如(GNU sed,在非 posix 模式下):
$ echo "abc:def" | sed -e 's/[^\s]\+:[^\s]\+/ : /g'
:
可能你想要的是更像是s/\([^[:blank:]]\):\([^[:blank:]]\)/\1 : \2/
例如
$ echo "abc:def" | sed -e 's/\([^[:blank:]]\):\([^[:blank:]]\)/\1 : \2/g'
abc : def
[据我所知,重复运算符\+
- 这也是不可移植的 - 是不必要的。]
答案2
尝试:
echo "abc:def" | sed 's@\([^\s]\):\([^\s]\)@\1 : \2@g'
我已经使用 GNU sed 对此进行了测试,不确定 BSD sed 是否如此。
如果您想保留原始匹配的部分内容,则需要捕获组,这就是 和\(...\)
和\1
正在\2
做的事情。另外,您不需要限定符,+
因为您只关心最近的邻居。