如何将 bash 变量(数值数据列表)传递给 gnuplot *不使用文件*

如何将 bash 变量(数值数据列表)传递给 gnuplot *不使用文件*

我正在使用 netcat 获取一系列我想用 gnuplot 绘制的点。但是,我在将数据传递到 gnuplot 时遇到问题,而不先将其写入文件。

在最简单的情况下,我想首先绘制一条在变量中定义的 3 点线,如下所示:

#!/bin/bash

DATA="10
12
15"

echo "$DATA"

# Data looks good in terminal (single vertical column of numbers 10, 12, 15)
# However, the following step doesn't work:

gnuplot -persist <<-EOFMarker
    plot $DATA w lines
EOFMarker

实际用例是从联网的 Rigol 示波器获取数据并将其显示在图表中。这是到目前为止的完整脚本:

#!/bin/bash
SERVER=192.168.0.12
PORT=5555

RIGOLDATA="$(echo ":TRAC:DATA? TRACE1" | netcat -q1 $SERVER $PORT | cut -c 13- | tr ',' '\n' | tr -d [:blank:])"
echo "$RIGOLDATA"

# RigolData looks good in terminal (single vertical column of numbers).
# However, the following does not work:

gnuplot -persist <<-EOFMarker
    plot $RIGOLDATA w lines
EOFMarker

我可以通过首先将数据传递到临时文件中来获得所需的结果,如下所示,但我试图避免使用临时文件:

#!/bin/bash
SERVER=192.168.0.12
PORT=5555

RIGOLDATA="$(echo ":TRAC:DATA? TRACE1" | netcat -q1 $SERVER $PORT | cut -c 13- | tr ',' '\n' | tr -d [:blank:])"

echo "$RIGOLDATA" > tempfile.csv


gnuplot -persist <<-EOFMarker
    plot "tempfile.csv" w lines
EOFMarker

答案1

plot $DATA w lines

扩展到

plot 10
12
15 w lines

即任何$DATA包含的内容都按字面意义放置在那里,换行符等等。这可能会破坏命令。 (我不确定 gnuplot 是否有办法直接在plot命令行上提供数据,但它可能需要采用其他格式。)

shell 具有进程替换功能,可以将命令的输出作为“文件”使用,并扩展为文件名,但您最好通过 stdin 传递数据,并将命令plot作为gnuplot选项提供。

基于所使用的示例命令这里,这样的事情可能会起作用:

echo "$DATA" | gnuplot -e 'plot "-" w lines'

或者更确切地说,直接从获取数据的地方传输数据,而不首先将其收集在 shell 中:

echo ":TRAC:DATA? TRACE1" | netcat -q1 "$SERVER" "$PORT" | 
  cut -c 13- | tr ',' '\n' | tr -d "[:blank:]" |
  gnuplot -e 'plot "-" w lines'

话又说回来,我不认为使用临时文件有那么糟糕。许多 shell 脚本都使用它们,非 shell 程序也使用它们。许多通常从 shell 脚本调用的程序可以直接读取文件,而从 shell 变量传递数据则需要更多复杂性。 (例如,管道echo "$var" | somecmd需要启动 shell 的额外副本来写入数据,而此处文档和此处字符串somecmd <<< "$var"可能会在后台创建一个临时文件......)

当然,您通常希望在完成后删除所有临时文件,并且应该确保它们是使用唯一的名称创建的,这样就不会发生冲突。但这并不难做到:

#!/bin/bash
server=192.168.0.12
port=5555
tempfile=$(mktemp)

echo ":TRAC:DATA? TRACE1" | netcat -q1 "$server" "$port" |
   cut -c 13- | tr ',' '\n' | tr -d "[:blank:]" > "$tempfile"


gnuplot -persist <<-EOFMarker
    plot "$tempfile" w lines
EOFMarker

rm -f -- "$tempfile"

答案2

好吧,我想分享我想到的简单答案,即安装和使用 feedgnuplot。

这将绘制一条连接 Y 坐标 4、8、5、7 的简单线:

echo -e "4\n8\n5\n7" | feedgnuplot -w lines

这将绘制一条连接 (x,y) 点 (3,11)、(4,15)、(5,12) 的简单线:

echo -e "3 11\n4 15\n5 12" | feedgnuplot -w lines --domain

还可以使用 --stream 选项频繁地重新绘制实时视图图的绘图。

这基本上就是我所寻找的,我现在在 Rigol DSA815 的稳定且快速更新的 bash 脚本中成功使用 feedgnuplot,如下所示:

while true; do
   printf "clear\n"
   echo ":TRAC:DATA? TRACE1" | netcat -N 192.168.0.12 5555 | cut -c 13- | tr ',' '\n' | tr -d [:blank:]
   printf "replot\n"
done | feedgnuplot --with 'lines lw 3' --stream 0 --exit --xlen 601

我希望这可以帮助任何尝试在不使用临时文件的情况下制作 gnuplot 图表的人!

相关内容