一个-k
选项是支持经典的Bourne shell,而Bash和Korn shell仍然支持。生效后,dd
命令行上任何位置的所有“ -like”命令选项都会自动转换为传递给命令的环境变量:
$ set -k
$ echo a=1 b=2 c=3
$
说服它们是环境变量要困难一些。运行这个对我有用:
$ set -k
$ env | grep '^[a-z]=' # No environment a, b, c
$ bash -c 'echo "Args: $*" >&2; env' a=1 b=2 c=3 | grep '^[a-z]='
Args:
a=1
b=2
c=3
$ set +k
$ bash -c 'echo "Args: $*" >&2; env' a=1 b=2 c=3 | grep '^[a-z]='
Args: b=2 c=3
$
第一个env | grep
没有使用单个小写字母演示任何环境变量。第一个bash
显示没有参数通过传递给脚本-c
,并且环境确实包含三个单字母变量。该set +k
取消-k
,也显示了相同的命令现在已经传递给它的参数。(该脚本a=1
被视为$0
脚本;您也可以通过适当的回显来证明这一点。)
这实现了问题所要解决的问题-键入./script.sh a=1 b=2
应该与type相同a=1 b=2 ./script.sh
。
请注意,如果在脚本中尝试以下技巧,则会遇到问题:
if [ -z "$already_invoked_with_minus_k" ]
then set -k; exec "$0" "$@" already_invoked_with_minus_k=1
fi
所述"$@"
被处理逐字; 不会重新分析以查找分配样式的变量(bash
和ksh
)。我试过了:
#!/bin/bash
echo "BEFORE"
echo "Arguments:"
al "$@"
echo "Environment:"
env | grep -E '^([a-z]|already_invoked_with_minus_k)='
if [ -z "$already_invoked_with_minus_k" ]
then set -k; exec "$0" "$@" already_invoked_with_minus_k=1
fi
echo "AFTER"
echo "Arguments:"
al "$@"
echo "Environment:"
env | grep -E '^([a-z]|already_invoked_with_minus_k)='
unset already_invoked_with_minus_k
并且仅already_invoked_with_minus_k
在exec
'd脚本中设置了环境变量。