该脚本应该能够在shell / bash脚本中更改argv [0]值。 我在一篇较旧的帖子上找到了但却无法理解它在做什么。 有人可以解释这条线的工作原理:
sh -c ". '$0'" argv0new "$@"
test ".$INNERCALL"
是否也是变量?
原始问题:How to change argv[0] value in shell / bash script?
#! /bin/bash # try executing this script with several arguments to see the effect
test ".$INNERCALL" = .YES || {
export INNERCALL=YES
# this method works both for shell and bash interpreters
sh -c ". '$0'" argv0new "$@"
# bash -c ". '$0'" argv0new "$@"
exit $?
}
printf "argv[0]=$0\n"
i=1 ; for arg in "$@" ; do printf "argv[$i]=$arg\n" ; i=`expr $i + 1` ;done
答案 0 :(得分:2)
当取消设置变量INNERCALL
时,脚本会使用一组特定参数调用自身。它设置变量以避免无限循环,然后以允许脚本设置自己的$0
的方式调用自身。然后内部实例执行test
之外的代码,这表明$0
现在确实设置为脚本作者选择的特定值。完成后,我们返回脚本的外部实例,然后退出。
真正的好处是sh -c 'script...' arg0 arg1 arg2
将$0
设置为脚本本身之后的第一个参数(在此示例中为arg0
)。
答案 1 :(得分:0)
请注意,它不会更改argv0的值,但会使用argv0new创建新进程
改变
sh -c ". '$0'" argv0new "$@"
通过
exec sh -c ". '$0'" argv0new "$@"
也可以通过sh改变bash。
对于bash From bash Invoking-Bash
-c
从第一个非选项参数command_string中读取并执行命令,然后退出。如果在command_string之后存在参数,则将第一个参数分配给$ 0,并将任何剩余的参数分配给位置参数。赋值为$ 0设置shell的名称,用于警告和错误消息。
答案 2 :(得分:0)
让我们一行一行地了解
test ".$INNERCALL" = .YES
基本上这会看到$INNERCALL
中是否已包含值YES
。 Shell的""
函数以安全的方式进行变量扩展,并将其全部编组为一个值,例如。
foo="hello"
bar=", world!"
echo "foobar is: $foo$bar"
打印foobar is: hello, world!
|| {
...
}
这使用||
运算符来表示,如果先前的程序返回非零值(例如test是一个程序,如果关联的条件为false则返回1),然后执行此代码块,否则跳过它(有关||
的更多信息,请参阅this link)
export INNERCALL=YES
这会将INNERCALL
设置为YES
,这意味着这只会针对第一级执行
sh -c ". '$0'" argv0new "$@"
exit $?
这就是魔术发生的地方。 sh -c
打开一个新shell,然后从后面的字符串中读取它的参数。 ". '$0'"
在当前sh
的值上使用$0
的源函数,该值应该是当前文件。
基本上sh -c ". '$0'"
只是在子sh
进程中再次打开当前文件,然后该行的其余部分替换参数:
argv0new
成为新的$ 0,并通过包括"$@"
然后exit $?
返回子进程运行的任何返回值。
其余代码只是为了证明除$0
之外的所有参数都相同,并且$0
已被替换。
tl; dr 它会打开一个子shell进程,告诉它读取当前文件,替换参数,然后导出一个测试值,使其不会无限循环。