奇怪的sed行为

时间:2018-02-06 19:14:21

标签: regex shell sed posix

我有这个符合POSIX标准的shell脚本。它需要一个带分隔符的字符串w.r.t. | -如果它们是单个字符的长度,则前缀为#!/bin/sh printf '%s\n' "k|k|jill|hill|k" | sed 's/\([|]\|^\)\([[:alnum:]]\)\([|]\|$\)/\1-\2\3/g'

-k|k|jill|hill|-k

输出:

|k|

请注意,它没有考虑夹在两个分隔符之间的k(即-)。

更奇怪的是,如果我将原始代码段中的特殊字符更改为其他内容,则会预先添加^(请注意更改:something$; {{1 }} different),但显然不是第一个和最后一个k:

#!/bin/sh
printf '%s\n' "k|k|jill|hill|k" | sed 's/\([|]\|something\)\([[:alnum:]]\)\([|]\|different\)/\1-\2\3/g'

输出:

k|-k|jill|hill|k

起初我认为这是因为$^位置字符不是可选的。但是,对于第一个标志中的$和第一个示例的最后一个标志中的^,它们显然是可选的。

我很好奇,为什么这不起作用,我可以用类似的sed表达式做我想做的事情吗?

2 个答案:

答案 0 :(得分:4)

请注意,如果您从全局搜索更改sed脚本并替换为循环,则可以获得所需的输出:

printf '%s\n' "k|k|jill|hill|k" | sed 's/\([|]\|^\)\([[:alnum:]]\)\([|]\|$\)/\1-\2\3/g'
-k|k|jill|hill|-k

printf '%s\n' "k|k|jill|hill|k" | sed '
    :a
    s/\([|]\|^\)\([[:alnum:]]\)\([|]\|$\)/\1-\2\3/
    ta
'
-k|-k|jill|hill|-k

参考:https://www.gnu.org/software/sed/manual/html_node/Programming-Commands.html

答案 1 :(得分:3)

引擎无法与中间的ViewGroupManager匹配,因为它之前的成功匹配是其字符(k)在它之前被消耗,并且它不能与另一个{{1}匹配}。如果你的输入字符串是:

k|

你会看到一个理想的输出。对于解决方法,我建议您设置|选项以启用ERE语法以使用字边界标记:

kk|k|jill|hill|k

或更一般地说:

-r