例如,如果我想从 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
使用( forperl
gawk
-e
表达) 代替-c
(代码/命令))。
(仅限于短脚本(Linux 上不超过 128KiB)。
或者通过不同的文件描述符和此处文档:
python2 /dev/fd/3 3<< 'EOF'
name = raw_input("Enter your name:")
EOF