在bash函数中更新变量并在提示符中使用它(PS1)

时间:2016-05-22 19:37:26

标签: bash shell scripting sh

我想要做的是调用PS1中的函数来更新函数内的变量。然后我喜欢使用该变量向PS1添加另一行。像吼叫:

my_func(){
   var="_RED_"
   echo "hello in red"
}
PS1="\[\033]0;\w\007\]"
PS1+='$(my_func)'
if [ $var = "_RED_" ]; then               # here I want to use that var
   PS1+="\[$(tput setaf 124)\] red"
fi

这样做的原因是将不可打印的字符\[\]从函数中移出,以防止重叠由\[ \]

引起的长行重叠

2 个答案:

答案 0 :(得分:3)

您可以绝对更新shell函数内的全局变量 - 函数内的所有赋值修改全局变量,除非使用localdeclare变量创建新范围。

然而,这里的问题是,您不能在与稍后尝试阅读var的代码相同的shell进程中运行您的函数(尽管它是否实际上是"稍后& #34;或者不是一个单独的问题)!当您使用命令替换 - $()中的$(my_func)时 - 您正在创建一个新的分叉子流程来运行该功能。当该子进程退出时,对其所做的变量值的所有更改都将丢失。

但是,您可以使用命令替换 not 来解决这个问题。请考虑以下内容,它使用PROMPT_COMMAND挂钩来指定PS1

# code to run before each time a prompt is printed
PROMPT_COMMAND='build_ps1_func'

# rewrite your function to write to a named variable, not stdout
my_func(){
   local outvar=$1; shift # named variable to write stdout to
   var="_RED_"            # hardcoded global to update, per question
   printf -v "$outvar" '%s' "hello in red"
}

build_ps1_func() {
  local your_str    # define your_str as a local variable
  my_func your_str  # call my_func, telling it to write output to your_str

  PS1="\[\033]0;\w\007\]"
  PS1+="$your_str"
  if [ $var = "_RED_" ]; then        # using that variable here
    PS1+="\[$(tput setaf 124)\] red"
  fi
}

答案 1 :(得分:0)

  

我想要做的是调用PS1中的函数来更新函数内部的变量。然后我喜欢使用该变量向PS1添加另一行。

从您的示例代码中,我想您的意思是您希望在为PS1赋值的过程中执行涉及shell函数的命令扩展。 [update:]由于您已经标记了问题[bash],我们假设您对GNU Bash的行为特别感兴趣,这与完全符合要求的POSIX shell的行为不同这个区域。 在这种情况下,重要的是要认识到在设置/修改PS1的值时,一次执行命令扩展,而不是每次显示PS1。你的措辞和具体语法让我怀疑你有不同的期望。

考虑这部分代码:

PS1="\[\033]0;\w\007\]"
PS1+='$(my_func)'

因为它出现在单引号中,所以$(my_func)在附加到提示字符串时不受命令扩展或任何其他扩展的限制。 尽管在将值附加到PS1之前删除了单引号,但这并不意味着它将在以后进行扩展。 与完全符合要求的POSIX shell不同, Bash将在打印之前对提示字符串执行命令替换。

现在,因为函数体是一个花括号复合命令,如果它被执行,那么它确实会在当前shell中设置var的值,并且该函数在函数返回后将可见。然而,

  1. (update,per @CharlesDuffy :)命令替换中的命令在子shell中运行。虽然该子shell中的变量更新将持续超过函数返回,但其范围仅限于子shell,后者几乎立即退出。
  2. 同样,您提供的代码中没有任何内容导致您的函数被调用,
  3. 即使它已被调用,并且它确实在当前shell中设置了var,您也要测试$var的值,与您的函数设置的值不同。
  4. 相反,请考虑代码的其他片段:

    PS1+="\[$(tput setaf 124)\] red"
    

    因为在这种情况下整个字符串是双引号,所以内容明确地受命令扩展的影响。如果执行此操作,$(tput setaf 124)将替换为运行tput setaf 124的输出。这将在PS1的值被修改时发生,而不是每次显示其值时都会发生。

    虽然您可以生成包含ANSI转义序列的提示,但您无法按照您尝试的方式执行此操作。由于您的具体需求尚不清楚,我不愿意提出一个特别的选择。