/bin/bash 和“.”之间的区别

/bin/bash 和“.”之间的区别

环境:Ubuntu 14.04

bc我的主文件夹中有一个名为的文件。该文件的全部内容是

func() {
    local a b=()
    echo $0
}
func

#!/bin/bash注意一开始是没有的。

然后,如果我这样做,/bin/bash ~/bc我会得到

/home/dev/bc

正如预期的那样。

但是,如果我改为获取它,. ~/bc则会收到以下错误:

bash: /home/dev/bc: line 2: syntax error near unexpected token `('
bash: /home/dev/bc: line 2: `    local a b=()'

我假设执行不同的 shell 来进行采购。如果是这样的话,我该如何改变呢?

如果我做一个chsh我得到

dev@c1:~$ sudo chsh
[sudo] password for dev: 
Changing the login shell for root
Enter the new value, or press ENTER for the default
    Login Shell [/bin/bash]: 

------ 来自评论 --------

echo $SHELL回报/bin/bash

答案1

问题几乎肯定是别名。当你这样做时:

/bin/bash somefile

您加载一个新的外壳。你会得到一个新的开始。该可执行文件并不包含您在初始化文件中放入的所有内容 -RCs - 因为这些默认情况下仅源自交互式 shell,更不用说此后产生的任何其他逻辑。

别名很奇怪。别名是解析器扩展 - 它们是大多数 shell 支持的第一种可扩展对象,并且它们以许多人意想不到的方式扩展。bash事实上,无论出于何种原因,通过alias在任何非交互式 shell 中默认禁用扩展来阻止它们的使用。因此,如果别名导致该错误 - 我很确定这就是问题所在 - 那么即使采购您的环境文件也可能仍然不会引发相同的错误输出/bin/bash,无论如何。

当我说别名很奇怪时,这是因为它们的扩展级别与其他类型的 shell 扩展不同。这可能在函数定义上下文中最为明显;其中没有发生 shell 扩展 - 因为这些扩展是为函数稍后执行而保留的 -除了别名无需对表达式进行两次求值。别名是绝不扩大期间函数执行(再次,缺少eval,因为他们是已经在其定义过程中进行了扩展。

这是一个例子:

alias a='echo not a;b'
b(){ echo a\?; }; a(){ echo le sigh...; }
a; b

...印刷...

not a
not a
le sigh...
le sigh...

第一次扩展alias命名a是当我这样做时:

a(){...

这是可能的,因为()括号是 shell 标记 - 不是像这样的保留字{}- 因此它们可以在没有空格的情况下分隔单词 - 这使得它们对于函数和数组声明等事情特别有用,因为解析器执行宏扩展以到达可执行语句。上述扩展的结果是......

}; echo not a;b(){ 

最后一次展开变换:

a; b

...进入...

echo not a;b; b

您会看到,典型的 shell 扩展发生在预先分隔的上下文中 - 它们的所有侧面都受到控制运算符的限制,例如:

\n[]{}|&();<>\'"`

通过这种方式,大多数 shell 扩展本身就充当了引用机制 - 从变量扩展出来的引号不会递归地界定进一步引用的上下文,因为扩展引用了它们。不过,别名扩展发生在此之前 - 如果解析器在扫描简单命令中的第一个 shell 单词时识别出别名,则别名会扩展 - 在扫描其余部分之前。因此,如果扩展结果不仅仅是一个简单的命令,那么......那就这样吧。

我的假设是你有一个alias声明 for func- 这将是最简单的解释 - 但因为别名可以链接,如果它们是用尾随空格定义的 - 并且也将被扩展之内函数定义 - 仅凭您提供的信息无法确定。不过,我想我可以重现你的错误。这很接近:

alias func='func('
func(){
    local a b=()
    echo $0
}
func

...打印...

bash: syntax error near unexpected token `('
bash: local: can only be used in a function
bash
bash: syntax error near unexpected token `}'
bash: syntax error near unexpected token `newline'

所以就这样做:

alias func local a b echo

请告诉我们。

相关内容