在我的.bash_profile
中,我有:
if [ -f $(brew --prefix)/etc/bash_completion ]; then
source $(brew --prefix)/etc/bash_completion
GIT_PS1_SHOWDIRTYSTATE=1
git_prompt='$(__git_ps1)'
fi
export PS1="[e[33m] d t w$git_promptn[e[m]\$ "
export MYTESTVAR="hello world"
我有一个Ruby脚本foo.rb
,其中包含:
`source ~/.bash_profile`
puts `printenv`
puts `echo $PS1`
puts `echo $MYTESTVAR`
当我运行ruby foo.rb
时,printenv
命令会列出所有环境变量,而$MYTESTVAR
行正确地返回hello world
。
但是,$PS1
没有出现。为什么会这样?
$MYTESTVAR行正确返回hello-world。$PS1未显示。
的确,你是对的。大多数变量工作正常,但"PS1"尤其失败:
$ PS1=ps1 TEST1=test1 ruby -e 'puts `echo $PS1 and $TEST1`'
and test1
为什么会这样?
在Ruby中,正如您可能知道的,`somestring`
在shell中执行somestring
,就好像您在C中打开了通往execl("/bin/sh", "-c", somestring, NULL)
的管道一样。
在许多系统中,/bin/sh
是由bash
提供的。Bash在其初始化代码中有以下片段:
/* Execute the start-up scripts. */
if (interactive_shell == 0)
{
unbind_variable ("PS1");
unbind_variable ("PS2");
interactive = 0;
换句话说,它显式地删除了"PS1"one_answers"PS2",因为这些变量仅用于交互式shell。
在dash
提供/bin/bash
的其他系统上,正如许多现代基于Debian的发行版默认的那样,您会得到您期望的结果:
$ PS1=ps1 TEST1=test1 ruby -e 'puts `echo $PS1 $TEST1`'
ps1 and test1
`source ~/.bash_profile`
不能解决这个问题的原因是每个`backtick command`
都在一个单独的shell中运行。在其中一个中设置的变量不会反映在另一个中。
如果你只想让shell导出变量,你应该按照@anujm的建议,直接用ENV['PS1']
获取它。这不仅更简单、更健壮,而且速度快了一千倍。
如果您想要.bash_profile
中设置的变量,无论您如何运行脚本,都可以在同一个shell中进行来源和打印:
puts `bash -c 'source ~/.bash_profile; printf "%s" "$PS1"'`