如何以交互方式从 bash 运行外部程序?

如何以交互方式从 bash 运行外部程序?

例如,如果我想从 shell 脚本运行 python 中的某些内容,我会这样做:

    echo 'print("hello world")' | python2

现在想象一下我想要运行一些交互式的东西,即它需要我的输入,例如

    name = raw_input("Enter your name:")

通过做:

    echo 'name = raw_input("Enter your name:")' | python2

我收到一个错误。那么从 bash 运行某些东西但我可以与之交互的正确方法是怎样的呢?

PS - 这只是一个例子。我需要在不同的外部程序(不是 python)中运行一组脚本,其中一些脚本需要用户的一些输入。一切都运行顺利,直到需要输入时,当前脚本崩溃并传递到下一个脚本。

谢谢 :)

答案1

当您将程序作为字符串传输到命令解释器时,解释器从其标准输入读取它,因此该标准输入绑定到管道的读取端:尝试从中交互提供的信息的命令通常会收到 EOF。

例如:

$ echo 'read x; echo "$x"' | bash
  # Just prints an empty line, doesn't wait for input

为了使这项工作有效,您需要:

  • 重写脚本以使其从不同的文件描述符读取交互式提供的输入,该文件描述符创建为运行整个管道的进程的标准输入的副本:

    { echo '0<&3 read x; echo "$x"' | bash; } 3<&0
    

    以 Python 为例(仅出于说明目的,我不是 Python 程序员):

    { echo 'import sys; \
      sys.stdin = open("/dev/fd/3"); \
      name = raw_input("Enter your name:")' | python2
    } 3<&0
    

    或者

  • 使解释器从不同的文件描述符读取,绑定到管道的读取和,并进行一些文件描述符改组,以使运行整个管道的进程的标准输入可供它使用。假设解释器接受脚本作为参数并且您的平台支持/dev/fd/n访问文件描述符的方式:

    { echo 'read x; echo "$x"' | bash /dev/fd/3 3<&0 0<&4; } 4<&0
    

    对于示例 Python 脚本:

    { echo 'name = raw_input("Enter your name:")' |
      { python2 /dev/fd/3
      } 3<&0 0<&4
    } 4<&0
    

    或者

  • 如果您的外部程序不接受脚本作为参数(既不是像中那样作为字符串bash -c 'echo "foo"',也不是像中那样作为文件名bash /dev/fd/3)并且需要读取脚本和来自标准输入的任何交互式提供的输入,您也许可以使用一些东西沿着这些思路:

    { echo 'echo start; echo "foo? "; read x; echo "$x"; echo end' |
      bash -c '0<&3 cat -
        while IFS= read -r x
        do
          printf "%s\n" "$x"
        done' 3<&0 0<&4 |
      bash
    } 4<&0
    

答案2

简单代码(希望你能明白):

read i && echo $i|python3

答案3

将脚本作为参数而不是 stdin 传递:

python2 -c 'name = raw_input("Enter your name:")'

请注意,没有什么可以阻止您将该脚本放在几行中,例如:

python2 -c '

# my fancy inline script
name = raw_input("Enter your name:")

'

(但请注意,对于包含 的 python 代码',您需要将其输入为'\'')。

interpreter -c <code>语法对于一些解释器来说是通用的。例如,这就是 shell 大部分时间运行的方式(system("some shell code")实际运行sh -c "some shell code")。其他一些解释器( //sed使用( forperlgawk-e表达) 代替-c代码/命令))。

(仅限于短脚本(Linux 上不超过 128KiB)。

或者通过不同的文件描述符和此处文档:

python2 /dev/fd/3 3<< 'EOF'
name = raw_input("Enter your name:")
EOF

相关内容