如何向gnuplot管道传输包含数据块的完整脚本?
我正在为gnuplot编写一个简单的Lua绑定,目前用execute执行系统shell命令、popen向gnuplot管道传输数据,行为和C语言里的类似。但popen是单向读写:以写入模式打开管道逐行传完整脚本时,没法读取gnuplot的stdout——我需要读取PNG图片的字节数组传给其他模块显示,而且只想用管道、避免临时文件。
我知道可以用-e参数通过命令行给gnuplot传命令,但没法用这个参数传入数据块。我需要一种能像执行脚本文件那样,向gnuplot管道传输包含命令和数据块的完整内容的方法。
我在Windows10的CMD环境下操作,希望优先用系统自带工具保证脚本可移植性,同时也能使用移植版GNU coreutils和GNU shell。
补充:echo plot x | gnuplot能实现命令管道传输,但我不知道怎么传数据块。数据块的创建格式如下:
$Mydata << EOD 11 22 33 44 55 66 77 88 99 EOD
行必须用换行符分隔,但CMD里的echo没法直接输出换行符。
方案1:Windows CMD原生实现
CMD本身不支持<< EOD这种Here Document语法,但可以通过以下两种方式绕开:
方式1:启用延迟变量扩展拼接多行内容
用cmd /v:on启用延迟变量扩展,通过^转义换行符,把命令和数据块拼接成完整的gnuplot脚本,再通过管道传入:
cmd /v:on /c "(echo set terminal png; echo $Mydata ^<^< EOD ^& echo 11 22 33 ^& echo 44 55 66 ^& echo 77 88 99 ^& echo EOD ^& echo plot $Mydata u 1:2)" | gnuplot
在Lua里调用时,可以把命令拼接成字符串,通过io.popen读取gnuplot的stdout:
local cmd = [[cmd /v:on /c "(echo set terminal png; echo $Mydata ^<^< EOD ^& echo 11 22 33 ^& echo 44 55 66 ^& echo 77 88 99 ^& echo EOD ^& echo plot $Mydata u 1:2)" | gnuplot]] local pipe = io.popen(cmd, "r") local png_bytes = pipe:read("*a") -- 读取完整的PNG字节数据 pipe:close() -- 将png_bytes传给其他模块处理
方式2:用多行括号结构生成输入
CMD支持用括号包裹多行echo命令,直接生成带换行的内容,再管道传给gnuplot:
( echo set terminal png echo $Mydata ^<^< EOD echo 11 22 33 echo 44 55 66 echo 77 88 99 echo EOD echo plot $Mydata using 1:2 ) | gnuplot
Lua里调用时,把多行内容转义成单行字符串即可:
local cmd = [[(echo set terminal png & echo $Mydata ^<^< EOD & echo 11 22 33 & echo 44 55 66 & echo 77 88 99 & echo EOD & echo plot $Mydata using 1:2) | gnuplot]] local pipe = io.popen(cmd, "r") local png_bytes = pipe:read("*a") pipe:close()
方案2:使用GNU Shell(如Windows版bash)
如果用GNU shell,直接支持Here Document语法,操作更简洁:
方式1:直接用Here Doc传递完整脚本
gnuplot << EOF set terminal png $Mydata << EOD 11 22 33 44 55 66 77 88 99 EOD plot $Mydata using 1:2 EOF
Lua里调用时,把脚本作为参数传给bash:
local cmd = [[bash -c 'gnuplot << EOF set terminal png $Mydata << EOD 11 22 33 44 55 66 77 88 99 EOD plot $Mydata using 1:2 EOF']] local pipe = io.popen(cmd, "r") local png_bytes = pipe:read("*a") pipe:close()
方式2:用GNU echo输出带换行的内容
GNU版本的echo支持-e参数解析转义字符,用\n表示换行:
echo -e "set terminal png\n\$Mydata << EOD\n 11 22 33\n 44 55 66\n 77 88 99\nEOD\nplot \$Mydata u 1:2" | gnuplot
注意要转义$符号,避免shell提前解析变量。
内容的提问来源于stack exchange,提问作者Sun of A beach

