为什么我无法在 Ruby 脚本中访问我的 bash 提示符?



在我的.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"'`

相关内容

  • 没有找到相关文章

最新更新