为什么这个Bash函数在git别名中执行两次,为什么添加`exit`修复它
如果我没有为某些基于函数的
Bash脚本显式调用
exit ,那么对于某些函数还会有其他意外的执行.是什么造成的?在将
git alias作为回答
another user’s question on StackOverflow的一部分时,首先注意到该行为.该别名由此脚本组成(它运行该函数两次而不是一次):
#!/usr/bin/env bash github(){ echo github; }; twitter(){ echo twitter; }; facebook(){ echo facebook; }; if [[ $(type -t "$1") == "function" ]]; then "$1"; else echo "There is no defined function for $1"; fi; 但是这个略微修改的脚本按预期执行(仅运行一次函数): #!/usr/bin/env bash github(){ echo github; }; twitter(){ echo twitter; }; facebook(){ echo facebook; }; if [[ $(type -t "$1") == "function" ]]; then "$1"; exit 0; else echo "There is no defined function for $1"; exit 1; fi; 这正是我通过git别名运行这些脚本时所发生的事情(添加 $git config --global alias.encrypt-for '!set -evu -o pipefail;github(){ echo github;};twitter(){ echo twitter;};facebook(){ echo facebook;};if [[ $(type -t "$1") == "function" ]];then "$1"; exit 0; else echo "There is no defined function for $1"; exit 1; fi;' $git encrypt-for "github" type -t "$1" github $git config --global alias.encrypt-for '!set -evu -o pipefail;github(){ echo github;};twitter(){ echo twitter;};facebook(){ echo facebook;};if [[ $(type -t "$1") == "function" ]];then "$1"; else echo "There is no defined function for $1"; fi;' $git encrypt-for "github" type -t "$1" github github set -x的输出: $git encrypt-for "github" ++ type -t github + [[ function == function ]] + github + echo github github + github + echo github github 使用echo“我在github中回显”替换echo github的输出作为排除echo命令作为第二个函数执行源的方法: $git encrypt-for "github" ++ type -t github + [[ function == function ]] + github + echo 'I am echo in github' I am echo in github + github + echo 'I am echo in github' I am echo in github 以下是别名/脚本的最简单版本,它提供了双重执行的不良行为: g(){ echo "once"; }; $1; 这是执行简化别名/脚本(具有执行两次的错误行为)的结果输出: $git config --global alias.encrypt-for '!g(){ echo "once";};$1;' $git encrypt-for g once once
那是因为git处理别名的方式:
给定别名 [alias] myalias = !string 其中string是代表某些代码的任何字符串,当调用git myalias args其中args是一个(可能是空的)参数列表时,git将执行: sh -c 'string "$@"' 'string' args 例如: [alias] banana = !echo "$1,$2,SNIP " 并打电话 git banana one 'two two' three git将执行: sh -c 'echo "$1,SNIP " "$@"' 'echo "$1,SNIP "' one 'two two' three 所以输出将是: one,two two,SNIP one two two three 在你的情况下, [alias] encrypt-for = "!g(){ echo "once";};$1;" 并打电话 git encrypt-for g git将执行: sh -c 'g(){ echo "once";};$1;"$@"' 'g(){ echo "once";};$1;' g 为清楚起见,让我以相同的形式重写: sh -c 'g(){ echo "once";};$1;"$@"' - g 我只更换了’g(){echo“一次”;}; $1;’部分(这将是sh的$0的位置参数,并且不会在这里发挥任何作用)通过伪参数 – .应该很清楚它就像执行: g(){ echo "once";};g;g 所以你会看到: once once 要解决这个问题:不要使用参数!只需使用: [alias] encrypt-for = "!g(){ echo "once";};" 现在,如果您确实想要使用参数,请确保根本不执行给定的尾随参数.一种可能性是添加一个尾随注释字符,如下所示: [alias] encrypt-for = "!g(){ echo "once";};$1 #" 对于您的完整示例,更简洁的方法也可以将所有内容包装在函数中: [alias] encrypt-for = "!main() { case $1 in (github) echo github;; (twitter) echo twitter;; (facebook) echo facebook;; (*) echo >&2 "error,unknown $1"; exit 1;; esac }; main" 希望你能理解git在别名的引擎盖下做什么!它确实将“$@”附加到别名字符串,并使用此字符串和给定的参数调用sh -c. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |