提问人:ychaouche 提问时间:12/22/2022 更新时间:12/22/2022 访问量:52
if 语句中 bash 函数定义的奇怪行为,语法为 foo(){} [duplicate]
Weird behavior of bash function definitions inside if statements with the foo(){} syntax [duplicate]
问:
让我们从一个有效的代码开始
$ cat foo1
#!/bin/bash
foo() {
echo "I'm here";
}
foo # prints: I'm here
$ ./foo1
I'm here
$
目前为止,一切都好。
现在我们来介绍一个语法错误
$ cat foo2
#!/bin/bash -i
alias foo="echo I am an alias"
foo() {
echo "I'm here";
}
foo # isn't reached
$ ./foo2
bash: ./foo2: line 4: syntax error near unexpected token `('
bash: ./foo2: line 4: `foo() { '
$
哎呀!让我们通过取消锯齿 FOO 来修复它。
$ cat foo3
#!/bin/bash -i
alias foo="echo I am an alias"
unalias foo
foo() {
echo "I'm here";
}
foo # prints:
$ ./foo3
I'm here
$
如果我们添加一个 if 条件会发生什么?
$ cat foo4
#!/bin/bash -i
alias foo="echo I am an alias"
if true
then
unalias foo
foo() {
echo "I'm here";
}
fi
foo # prints:
$ ./foo4
bash: ./foo4: line 7: syntax error near unexpected token `('
bash: ./foo4: line 7: ` foo() { '
$
为什么?为什么它在 if 条件下失败,但过去在没有 if 条件的情况下工作?
如果我们使用语法而不是 ?function foo{}
foo(){}
$ cat foo5
#!/bin/bash -i
alias foo="echo I am an alias"
if true
then
unalias foo
function foo {
echo "I'm here";
}
fi
foo # prints:
$ ./foo5
I'm here
$
它现在有效吗?
问:为什么 foo2 和 foo4 会断裂?
答:
4赞
glenn jackman
12/22/2022
#1
因为别名首先发生,所以函数定义变成这样(在 bash 替换别名之后:
echo I am an alias() { echo "I'm here"; }
这显然是一个语法错误。
别名仅在命令的第一个单词上替换。当您使用关键字来定义函数时,您就避免了别名扩展的可能性。
function
这可能是在非交互式 shell 中默认关闭别名的原因之一。
评论
5赞
oguz ismail
12/22/2022
..foo4 中断,因为在复合命令中使用 alias/unalias 所做的更改在完成之前不会生效; 也不起作用if alias foo='echo a'; then foo; fi
0赞
ychaouche
12/22/2022
您@glenn建议使用关键字而不是使用 parens?function
1赞
ShadowRanger
12/22/2022
@ychaouche:不能接受格伦的建议,但是的,使用关键字。如您所见,它可以保护您免受无意中的别名冲突的影响。类似于当您想要确保运行可执行文件而不显式提供硬编码路径时,如何使用(或当您不信任用户的 )作为前缀来绕过 shell 函数(并且隐式别名,因为实际命令不再作为第一个单词出现)。 还可以更轻松地查找稍后定义的函数,而不是滚动和跳跃。function
command
command -p
PATH
function
3赞
glenn jackman
12/23/2022
我的建议是停止在脚本中使用别名。请改用函数。
2赞
David
12/22/2022
#2
我只是添加参考,因为公认的答案(连同第一条评论)是正确的。
从手册页:bash
The rules concerning the definition and use of aliases are somewhat
confusing. Bash always reads at least one complete line of input, and
all lines that make up a compound command, before executing any of the
commands on that line or the compound command. Aliases are expanded
when a command is read, not when it is executed. Therefore, an alias
definition appearing on the same line as another command does not take
effect until the next line of input is read. The commands following
the alias definition on that line are not affected by the new alias.
This behavior is also an issue when functions are executed. Aliases
are expanded when a function definition is read, not when the function
is executed, because a function definition is itself a command. As a
consequence, aliases defined in a function are not available until af‐
ter that function is executed. To be safe, always put alias defini‐
tions on a separate line, and do not use alias in compound commands.
魔鬼在细节中(f#*@!n' 手册)。
下一个:如何从 txt 文件中提取数字
评论