shell脚本,用输入执行程序并保存输入与输出中的输出相结合



我正在开发一个分配服务器,学生可以在其中上传他们的程序解决方案。它应该使用几种编程语言。用于测试程序,我正在执行外壳脚本并将测试案例和文件作为参数传递:

printf '10n3n+n' | ./eval_python steps.py

它的工作,这不是问题。对于输出,我得到了类似的东西:

使用Shell脚本运行Python脚本:

$ How much steps? Step size? Counting up (+) or down (-) ? Step   0:     3
$ Step   1:     6
$ Step   2:     9
$ Step   3:    12
$ Step   4:    15
$ [..]

这种格式使评估非常困难,也可能使学生感到困惑,因为他们看不到输入(当您从Shell中运行Python脚本时,输出在下面的示例中看起来都如下)。为了评估困难,学生不得像本解决方案中那样命名他们的输入,如果他们只问Steps?而不是How much steps?

也可以。

直接从Shell运行Python脚本:

$ How much steps?  10
$ Step size? 3
$ Counting up (+) or down (-)? +
$ Step   0:     3
$ Step   1:     6
$ Step   2:     9
$ Step   3:    12
$ Step   4:    15
$ [..]

有没有办法将输入组合在输出中?或其他想法我如何解决此问题?

非常感谢!

处理用户提示自动更难,而printf不足以完全模拟它。如果您不想触摸Python代码本身,则可能必须使用expect,这是一种写作的脚本语言来处理交互式程序。

如果不在系统上(可能是),请使用sudo apt install expectsudo yum install expect安装。我在一起的这种粗糙的东西应该能够处理您的要求:

Expect_Script.exp

#!/usr/bin/expect -f
set steps [lindex $argv 0]
set size [lindex $argv 1]
set plus_or_minus [lindex $argv 2]
set script_name [lindex $argv 3]
spawn python3 ${script_name}
# Or `spawn eval_python ${script_name}`, as long as it is a python 3 interpreter as well
# If it is python 2, all `input` calls within need to be changed to `raw_input`
expect "steps"
send -- "${steps}r"
expect "size"
send -- "${size}r"
expect "Counting"
send -- "${plus_or_minus}r"
expect eof

然后这样称呼:

./expect_script.exp 10 3 + steps.py

如果您对语法或语义有疑问,请随时提出。但是不要期待太多(哈哈),我在怪异的Unix工具方面不是很好。


使用可变数量的参数编辑:

Expect_Script.exp

#!/usr/bin/expect -f
spawn python3 [lindex $argv 0]
# Or `spawn eval_python [lindex $argv 0]`, as long as it is a python 3 interpreter as
# well. If it is python 2, all `input` calls within need to be changed to `raw_input`.
set sleep_time 0.1  # using `sleep` to wait for the next prompt is, usually,
                    # a very bad idea. Maybe you can control your input calls
                    # by including unique identifiers in them, such as 1, 2, 3..
                    # and using `except` to properly wait for them?
for {set i 1} {$i < [llength $argv]} {incr i 1} {
 sleep $sleep_time  
 send -- [lindex $argv $i]r
}
expect eof

呼叫顺序已更改,因为我们需要在发送参数的方式之前拨打python脚本:

./expect_script.exp test.py 10 3 +

或者,更改Python脚本以接受命令行参数。如果您打算执行任务自动化或重复使用代码,或者仅在一般而言 - 命令行参数几乎总是比用户提示更好的主意。本机Python ArgParse模块非常好,即使您不想重写当前代码,也可能值得研究它并尝试在将来应用它。

可以使您的所有流都"需求驱动",但这不是一项琐碎的任务,尤其是脚本。我的意思是,只有当管道说需要更多输入时,每个输入字符串才传递到管道中。同样,您必须在准备就绪后立即收集输出。通过执行此操作,您可以将输入和输出流组合在一起,以便制作明智的报告。

请注意,您可能需要注入一些新线才能使其真正可读。

也许另一种方法是告诉用户他们必须提出特定问题。

让您的安全带按字符读取输出字符(我知道),并且一旦它与一个特定的预期问题匹配,然后将匹配的答案注射为输入,但每次匹配只有一次。当然,一旦满足了所有问题,您就可以切换到更快的批处理。

然后,您可以按字节输出传输字节,并以自然顺序对日志文件进行注入的响应,该响应与您的安全带所做的事情相匹配。对于利用物而言,有暂停并打印出不需要的问题作为诊断辅助可能是一件好事。

这允许提到的问题排序,可选问题等,但硬线将设计规范的一部分符合客户要求。向学生们清楚地表明,他们将失去标记,因为不够适合自动化处理器的提示,或者说是提供本地语言翻译的客户。

最新更新