Bash 在命令行中动态建立环境变量
我有以下脚本:Bash 在命令行中动态建立环境变量,bash,parsing,Bash,Parsing,我有以下脚本: #!/bin/bash echo $FAV_FRUIT echo $FAV_HERO 以及以下txt文件: FAV_FRUIT='watermelon' FAV_HERO='batman' 我试图理解为什么这不起作用: $(cat environment.txt | tr '\n' ' ' ) ./printEnv.sh bash: FAV_FRUIT='watermelon' FAV_HERO='batman' : command not found 但如果我真的这么
#!/bin/bash
echo $FAV_FRUIT
echo $FAV_HERO
以及以下txt文件:
FAV_FRUIT='watermelon'
FAV_HERO='batman'
我试图理解为什么这不起作用:
$(cat environment.txt | tr '\n' ' ' ) ./printEnv.sh
bash: FAV_FRUIT='watermelon' FAV_HERO='batman' : command not found
但如果我真的这么做:
FAV_FRUIT='watermelon' FAV_HERO='batman' ./printEnv.sh
然后我得到正确的输出
如何修复命令以使其成功?在文件
printEnv.sh
中,您可以将此行添加为第一行(shebang之后):
source environment.txt
在文件
printEnv.sh
中,您可以将该行添加为第一行(在shebang之后):
source environment.txt
我不认为错误消息来自您声称执行的行:
$ $(cat environment.txt | tr '\n' ' ' ) ./printEnv.sh
FAV_FRUIT='watermelon': command not found
这是我认为你写的。看到区别了吗
$ "$(cat environment.txt | tr '\n' ' ' )" ./printEnv.sh
FAV_FRUIT='watermelon' FAV_HERO='batman' : command not found
无论如何,$(…)
替换被视为命令(或者,在第一种情况下,是命令和参数)而不是临时变量赋值的原因很简单。语法var=value prog args
就是:语法。Bash首先解析命令行,然后再进行任何替换,并且在解析过程中,它会标识作为临时环境分配的单词
解析命令后,它会找出哪些单词是临时赋值,哪些是重定向,并将它们分开。然后,它进行各种替换,之后它将响应剩余的字(引用的字除外),并使用第一个字作为执行命令。(参数赋值和重定向也会进行替换,但不会进行分词。之后它们仍然是赋值和重定向。)
这意味着在键入作业时,作业必须看起来像作业。变量名必须是有效的变量名,因此不能包含任何替换。只有值部分进行替换
完成您似乎要做的事情的最简单方法是使用标准命令行实用程序env
。例如,您可以编写:
env $(cat environment.txt | tr '\n' ' ' ) ./printEnv.sh
但是要小心!当bash进行替换时,文本文件中的单引号不会被删除。因此,结果将是:
'watermelon'
'batman'
而不是
watermelon
batman
要获得正确的输出,只需在文件中保留单引号。请注意,tr
命令是不必要的,因为分词也适用于换行符
到目前为止还不错。但是,只有当文件environment.txt
中没有一行包含空格或制表符,或者任何其他可能被扩展的字符(例如*
)时,这才有效。这不太令人满意。您不能只引用$(…)
,因为这样它将是一个单独的参数,env
将其视为一个单独的环境赋值(就像它在最初的尝试中被视为一个表示命令名的单词一样)
这个问题的通常解决方案是使用bash数组。(同样,我从environment.txt
中删除了单引号,这样可以正常工作。)
$mapfile assignments
我不认为错误消息来自您声称执行的那行代码:
$ $(cat environment.txt | tr '\n' ' ' ) ./printEnv.sh
FAV_FRUIT='watermelon': command not found
这是我认为你写的。看到区别了吗
$ "$(cat environment.txt | tr '\n' ' ' )" ./printEnv.sh
FAV_FRUIT='watermelon' FAV_HERO='batman' : command not found
无论如何,$(…)
替换被视为命令(或者,在第一种情况下,是命令和参数)而不是临时变量赋值的原因很简单。语法var=value prog args
就是:语法。Bash首先解析命令行,然后再进行任何替换,并且在解析过程中,它会标识作为临时环境分配的单词
解析命令后,它会找出哪些单词是临时赋值,哪些是重定向,并将它们分开。然后,它进行各种替换,之后它将响应剩余的字(引用的字除外),并使用第一个字作为执行命令。(参数赋值和重定向也会进行替换,但不会进行分词。之后它们仍然是赋值和重定向。)
这意味着在键入作业时,作业必须看起来像作业。变量名必须是有效的变量名,因此不能包含任何替换。只有值部分进行替换
完成您似乎要做的事情的最简单方法是使用标准命令行实用程序env
。例如,您可以编写:
env $(cat environment.txt | tr '\n' ' ' ) ./printEnv.sh
但是要小心!当bash进行替换时,文本文件中的单引号不会被删除。因此,结果将是:
'watermelon'
'batman'
而不是
watermelon
batman
要获得正确的输出,只需在文件中保留单引号。请注意,tr
命令是不必要的,因为分词也适用于换行符
到目前为止还不错。但是,只有当文件environment.txt
中没有一行包含空格或制表符,或者任何其他可能被扩展的字符(例如*
)时,这才有效。这不太令人满意。您不能只引用$(…)
,因为这样它将是一个单独的参数,env
将其视为一个单独的环境赋值(就像它在最初的尝试中被视为一个表示命令名的单词一样)
这个问题的通常解决方案是使用bash数组。(同样,我从environment.txt
中删除了单引号,这样可以正常工作。)
$mapfile assignments
如果不想将$()的结果解释为命令,可以使用env
:
env $(cat environment.txt | tr '\n' ' ' ) ./printEnv.sh
与导出不同,env
仅临时设置变量。如果您在之后执行echo$FAV_FRUIT,您将得到一个空输出
请参见如果不希望$()的结果被解释为命令,可以使用
env