为什么 GNU sed 将不匹配的行内容添加到使用“e”修饰符执行的命令中

为什么 GNU sed 将不匹配的行内容添加到使用“e”修饰符执行的命令中

以下命令可以正确使用 UID 和 GID 替换文本用户名和组名:

echo "uidNumber=root" | sed -E 's/((u|g)idNumber=)([^,+]+)/echo -n \1; id -\2 \3/eg'
uidNumber=0

但是,如果在模式匹配的文本之前添加文本,则会将其添加到替换中执行的命令之前并导致失败:

echo "anotherAttr,uidNumber=root" | sed -E 's/((u|g)idNumber=)([^,+]+)/echo -n \1; id -\2 \3/eg'
h: line 1: anotherAttr,echo: command not found
0

如果在模式匹配的文本之后添加文本,似乎也会发生同样的情况,在这种情况下,它会被附加:

echo "anotherAttr1,uidNumber=root,anotherAttr2" | sed -E 's/((u|g)idNumber=)([^,+]+)/echo -n \1; id -\2 \3/eg'
sh: line 1: anotherAttr1,echo: command not found
id: ‘root,anotherAttr2’: no such user

为什么在执行的命令中附加和前置不匹配的文本,如何阻止这种情况发生?

编辑:其他用户建议匹配整行,但这会阻止g修改器正常运行,并且不是可接受的解决方案。

答案1

这个问题是由于对修改器工作原理的根本误解造成的e

替换s可以应用一次,也可以应用到整个模式缓冲区(在 的情况下g)。e然后在执行替换后执行模式缓冲区的内容。

修复方法非常简单,转义美元和斜杠,添加echo -n "到模式缓冲区,追加"到模式缓冲区,并将所有每个替换命令放入子 shell 扩展中。

添加p通过向我们展示将执行的内容来帮助调试:

echo "anotherAttr1,uidNumber=root,gidNumber=root,anotherAttr2" | sed -E 's/\\/\\\\/g;s/\$/\\$/g;s/^/echo "/;s/$/"/;s/((u|g)idNumber=)([^,+]+)/\1$(id -\2 \3)/peg'
echo "anotherAttr1,uidNumber=$(id -u root),gidNumber=$(id -g root),anotherAttr2"
anotherAttr1,uidNumber=0,gidNumber=0,anotherAttr2

相关内容