如果我运行以下 .sh 文件:
#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'
结果是一个错误:
sed:-e表达式#1,字符18:无效范围结束
但是如果我运行以下 .sh 文件:
#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'
它运行没有错误。第二个代码不应该与第一个代码等效吗?为什么第一个错误?
答案1
当使用名称调用 bash 时sh
,它做这个:
if (shell_name[0] == 's' && shell_name[1] == 'h' && shell_name[2] == '\0')
act_like_sh++;
然后后来设置POSIXLY_CORRECT
为y
:
if (act_like_sh)
{
bind_variable ("POSIXLY_CORRECT", "y", 0);
sv_strict_posix ("POSIXLY_CORRECT");
}
bind_variable
调用bind_variable_internal
,如果 shell 属性a
当时处于打开状态(如果您使用 调用 shell,则会出现这种情况-a
),将 shell 变量标记为出口。
所以在你的第一个脚本中:
#!/bin/sh -a
echo "a" | sed -e 's/[\d001-\d008]//g'
sed
在其环境中调用 with POSIXLY_CORRECT=y
,这将使其抱怨[\d001-\d008]
. (如果为 sed 提供该--posix
选项,也会发生同样的情况。)
在 GNU sed 中,是字符的转义码,其以 10 为基数的数值为\dNNN
神经网络,但在 POSIX 模式下,这在方括号表达式内被禁用,因此[\d001-\d008]
, 字面意思是字符\
,d
等,范围是从1
到\
。按照字符代码的顺序,1
位于前面\
(范围包括除零之外的所有数字,加上所有大写字母,加上一些特殊字符)。但是,在en_US.UTF-8
您使用的区域设置中,\
排序在 之前1
,因此范围无效。
在你的第二个脚本中:
#!/bin/sh
set -a
echo "a" | sed -e 's/[\d001-\d008]//g'
即使POSIXLY_CORRECT
在 shell 中设置,它也不会被导出,因此 sed 会POSIXLY_CORRECT
在没有环境的情况下被调用,并且 sed 使用 GNU 扩展运行。
如果您export POSIXLY_CORRECT
在第二个脚本的顶部附近添加,您还会看到 sed 抱怨。