如何从需要交互性的外部函数中获取值?

时间:2016-09-30 23:22:00

标签: bash function shell

我经常使用的一个例程是检查调用脚本时传递的有效参数。理想情况下,我想制作这些以及其他类似的例程,我可以从任何脚本调用外部函数来处理这些更简单的过程。但是,我无法从所述函数中检索所需的值,而不会使该过程更复杂。

我尝试过使用命令替换(例如,将外部函数的输出回显到调用脚本本地的变量名),这似乎至少适用于更简单的函数。但是,使用此文件检查功能需要循环中的read命令,因此需要用户交互性,这会导致脚本在尝试解析存储函数调用的变量时挂起:

#!/bin/bash
# This is a simple function I want to call from other scripts.
exist(){
  # If the first parameter passed is not a directory, then the input is 
  #+ invalid.
  if [ ! -d "$1" ]; then
    # Rename $1, so we can manipulate its value.
    userDir="$1"
    # Ask the user for new input while his input is invalid.
    while [ ! -d "$userDir" ]; do
      echo "\"$userDir\" does not exist."
      echo "Enter the path to the directory: "
      read userDir
      # Convert any tildes in the variable b/c the shell didn't get to
      #+ perform expansion.             
      userDir=`echo "$userDir" | sed "s|~|$HOME|"`
      done
    fi
}
exist "$1"

如何在不增加(太多)复杂性的情况下检索调用脚本中userDir的值?

2 个答案:

答案 0 :(得分:0)

马上就可以说我可以回复' stderr上的用户,并在stdout上回显您的预期答案。 我不得不重新排列以使其正常工作,但这已经过测试:

exist(){
    # If the first parameter passed is not a directory, then the input is
    #+ invalid.
    userDir="$1"
    if [ ! -d "$userDir" ]; then
        # Ask the user for new input while his input is invalid.
        while [ ! -d "$userDir" ]; do
            >&2 echo "\"$userDir\" does not exist."
            >&2 echo "Enter the path to the directory: "
            read userDir
        done
    else
        >&2 echo "'$1' is indeed a directory"
    fi
    echo "$userDir"
}

当我测试时,我将其保存到名为exist.inc.func

的文件中

然后我写了另一个使用它的脚本:

#!/bin/sh
source ./exist.inc.func

#Should work with no input:
varInCallingProg=$(exist /root)
echo "Got back $varInCallingProg"

#Should work after you correct it interactively:
varInCallingProg2=$(exist /probablyNotAdirOnYourSystem )
echo "Got back $varInCallingProg2"

答案 1 :(得分:0)

您可以让exists函数通过stderr与用户交互,并仍然使用命令替换捕获变量。我们来看一个简化的例子:

exist() { read -u2 -p "Enter dir: " dir; echo "$dir"; }

选项-u2告诉read使用文件描述符2(stderr)与用户进行交互。即使已通过命令替换重定向stdout,这仍将继续有效。选项-p "Enter dir: "允许read设置提示并在一个命令中捕获用户输入。

作为其工作原理的一个例子:

$ d=$(exist)
Enter dir: SomeDirectory
$ echo "$d"
SomeDirectory

完整示例

exist() {
    local dir="$1"
    while [ ! -d "$dir" ]; do
        echo "'$dir' is not a directory." >&2
        read -u2 -p "Enter the path to the directory: " dir
    dir="${dir/\~/$HOME}"
    done
    echo "$dir"
}

作为使用中的一个例子:

$ d=$(exist /asdf)
'/asdf' is not a directory.
Enter the path to the directory: /tmp
$ echo "new directory=$d"
new directory=/tmp

注意:

  1. 不需要if语句 while循环。 while就足够了。

  2. 单引号可以放在没有转义的双引号字符串中。因此,如果我们将错误消息写为"'$dir' is not a directory.",则不需要转义。

  3. 所有shell变量都应该是双引号,除非人们希望它们受到分词和路径名扩展的影响。