【问题标题】:Bash script running other bash scripts with user input使用用户输入运行其他 bash 脚本的 Bash 脚本
【发布时间】:2023-03-04 04:07:02
【问题描述】:

假设我有一个依赖于用户输入的 bash 脚本(使用 read 等)。

我现在想运行这个脚本 N 次,每次调用都接受一个参数,并且这些参数是从文本文件中读取的。所以本质上我想“为文本文件调用脚本中的每一行以行作为参数并让用户与之交互”。

但是,当我通过“forall”循环调用我的脚本时,我的 read 调用只是被跳过,没有读取用户输入。

简单的例子:

hello.sh:

name=$1
read -p "How old are you, $name? " age

echo "Hello $name, you are $age years old"

这可以很好地调用为

$ ./hello.sh Adam
How old are you, Adam? <user enters 42>
Hello Adam, you are 42 years old

现在我创建我的名称文件:

names.txt:

Andrew
Benjamin
Charles
David
Edward

还有我的forall 脚本:

forall.sh:

file=$1
command=$2

while read line; do
    if [ ! -z "$line" ]; then
        $command $line
    fi
done < $file

我现在做forall.sh names.txt ./hello.sh,希望我的 5 个用户输入他们的年龄,但我得到了这个:

$ forall.sh names.txt ./hello.sh
Hello Andrew, you are Benjamin years old
Hello Charles, you are David years old
Hello Edward, you are  years old

显然,read 调用将使用 names.txt 文件中的一行,而不是从提示符中读取。

我怎样才能“为文件中的每一行调用脚本中的每一行”并且仍然让被调用的脚本接受用户输入?

【问题讨论】:

  • 一个更好的设计是在子进程中避免read。许多需要交互式 I/O 的脚本也提供了将所需参数作为命令行选项传递的可能性。

标签: bash shell


【解决方案1】:

stdin 不是该循环中的终端,它被设置为&lt; $file。您需要将终端作为标准输入显式传递给该命令:

while read -r line; do
    if [ ! -z "$line" ]; then
        $command "$line" < /dev/tty
    fi
done < "$file"

【讨论】:

    【解决方案2】:

    或者,while-read 循环可以使用不同的文件描述符(不是标准输入)

    # ..............vvv
    while read line <&3; do
        [ -n "$line" ] && "$command" "$line"
    done 3< "$file"
    # ...^^
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-18
      • 1970-01-01
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 2011-07-27
      • 2013-11-01
      • 2018-12-13
      相关资源
      最近更新 更多