regex - 奇怪的 sed 行为

标签 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$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 表达式做我想做的事吗?

最佳答案

请注意,如果将 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

关于regex - 奇怪的 sed 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48650329/

相关文章:

regex - 如何习惯匿名化文件中的所有电子邮件地址

Javascript 正则表达式-如何在组内查找 PascalCase 项目

ruby-on-rails - 重定向 ruby​​ 脚本的 shell 输出

linux - 如何使用通配符从 linux 中的一行中删除特定模式

linux - linux 中的 wc -c 是如何工作的?

linux - 在子文件中查找最小值和最大值并将结果与​​父文件相关联

使用 OR 运算符和可视模式选择文本的多种模式的 Vim 替换

regex - 匹配 ssh 连接字符串的正则表达式

regex - 根据创建日期移动文件

C# 正则表达式,包含包含星号的单词