环境: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
请告诉我们。