如何向gnuplot传递命令行参数?

165

我想使用gnuplot从数据文件绘制图形,比如说foo.data。目前,我在命令文件中硬编码了数据文件名,比如foo.plt,然后运行命令gnuplot foo.plg来绘制图形。但是,我希望将数据文件名作为命令参数传递,例如运行命令gnuplot foo.plg foo.data。如何解析gnuplot脚本文件中的命令行参数?谢谢。

10个回答

209
你可以通过switch -e 输入变量。
$ gnuplot -e "filename='foo.data'" foo.plg

在foo.plg中,您可以使用该变量。

$ cat foo.plg 
plot filename
pause -1

为了使“foo.plg”更加通用,使用条件语句:

if (!exists("filename")) filename='default.dat'
plot filename
pause -1

请注意,-e 必须在文件名之前使用,否则文件将在 -e 语句之前运行。特别地,当使用 ./foo.plg -e ... 命令行参数来运行一个带有 shebang gnuplot #!/usr/bin/env gnuplot 的脚本时,会忽略提供的参数。


20
这也可以与if一起使用来提供默认值。if ! exists("filename") filename='default.data' - mgilson
10
对于现在偶然看到这条信息的人,mgilson的评论和Gnuplot 4.6补丁级别3需要使用if (!exists("filename")而不是if ! exists("filename") - Sam Mussmann
我在这里写了一个环境变量传递方法的简短示例:http://41j.com/blog/2011/10/grabbing-environment-variables-in-gnuplot/ - new299
6
@Chong: 要么将它们串在一起,要么在每个-e参数中分别给出,例如 -e "filename='default.data'; foo='bar'" 或者 -e "filename='default.data'" -e "foo='bar"' - Thor
1
注意:-e ...选项必须在文件名之前。事实上,从 man gnuplot 中可以读到:-e "命令列表" 在加载下一个输入文件之前执行请求的命令。 - Hastur
显示剩余3条评论

72

自5.0版本起,您可以通过标志-c向gnuplot脚本传递参数。这些参数可通过变量ARG0ARG9访问,其中ARG0是脚本,ARG1ARG9是字符串变量。参数的数量由ARGC给出。

例如,以下脚本("script.gp"):

#!/usr/local/bin/gnuplot --persist

THIRD=ARG3
print "script name        : ", ARG0
print "first argument     : ", ARG1
print "third argument     : ", THIRD 
print "number of arguments: ", ARGC 

可以称之为:

$ gnuplot -c script.gp one two three four five
script name        : script.gp
first argument     : one
third argument     : three
number of arguments: 5

或者在gnuplot内部

gnuplot> call 'script.gp' one two three four five
script name        : script.gp
first argument     : one
third argument     : three
number of arguments: 5
在gnuplot 4.6.6及更早的版本中,存在一种不同(现在已弃用)语法的call机制。参数可通过$#$0、...、$9来访问。例如,上面的脚本可写成:
#!/usr/bin/gnuplot --persist

THIRD="$2"
print "first argument     : ", "$0"
print "second argument    : ", "$1"
print "third argument     : ", THIRD
print "number of arguments: ", "$#"

在gnuplot中被称为(请记住,版本<4.6.6)

gnuplot> call 'script4.gp' one two three four five
first argument     : one
second argument    : two
third argument     : three
number of arguments: 5

请注意脚本名称没有变量,因此$0是第一个参数,并且变量在引号中调用。无法直接从命令行使用此功能,只能通过像@con-fu-se建议的技巧来实现。


我尝试在一个包含诸如 plot 'data' using 0:($1/100) 的脚本中使用 -c 开关。由于 $1 消失了,gnuplot 报错 _invalid expression_。我错在哪里?请注意,没有 -c,脚本可以成功运行。 - lorcap
我用gnuplot 5.0测试过了,通过添加类似于plot 'data' using 0:($1/100)的一行到这些示例中,我没有得到你说的结果。这很奇怪,因为这个版本定义了变量ARG0-ARG9,而不是$1-$9。我假设你也有5.0版本(对吗?),因为-c标志不受早期版本支持。我需要看到一个最小的脚本来确定真正的问题所在 :/ - vagoberto
我正在cygwin下运行gnuplot 5.0 patchlevel 0。这个一行脚本print ARG1; plot 'data' using 0:($1/100)正确地打印了传递的值作为ARG1,然后在斜杠处退出并指向无效表达式错误_invalid expression_ - lorcap

28
你还可以像这里建议的那样通过环境传递信息。 这里是的示例:
在shell中:
export name=plot_data_file

在 Gnuplot 脚本中:

#! /usr/bin/gnuplot

name=system("echo $name")
set title name
plot name using ($16 * 8):20 with linespoints notitle
pause -1

6
不需要导出,您可以键入 name=plot_data_file ./the_gnuplot_script - Edgar Bonet
@Edgar Bonet: 需要哪个gnuplot版本才能运行这个程序?在我使用的4.2版本的机器上似乎无法正常工作... - Bjoern
嗨@Bjoern!我正在使用Gnuplot 4.6,但这不是Gnuplot的功能,而是shell的一个功能:name=value command告诉shell在其环境中运行该特定变量的命令。我正在使用bash 4.3.11,但我相信这是一个非常常见的shell功能。 - Edgar Bonet

25

Jari Laamanen的答案是最好的解决方案。我只想解释如何使用多个输入参数与shell变量:

output=test1.png
data=foo.data
gnuplot -e "datafile='${data}'; outputname='${output}'" foo.plg

以及 foo.plg:

set terminal png
set outputname 
f(x) = sin(x)
plot datafile

正如您所看到的,更多的参数用分号传递(就像在bash脚本中一样),但是字符串变量需要用 ' ' 包围起来(这是gnuplot语法,不是Bash语法)


1
对于gnuplot本身来说,使用'"表示字符串并没有区别。但是,在-e参数的外部引号必须为",以便进行bash变量替换。以下方式也可以正常工作:OUTPUT=foobar; gnuplot -e "output=\"$OUTPUT\"; print output" - Christoph
谢谢确认我可以使用分号来分隔命令。其他答案都没有显示这个。 - tommy.carstensen
你的代码只有一个小错误:应该是 set output outputname 而不是仅仅的 set outputname - pulsar_hh

14

在Unix/Linux环境下,您可以使用以下技巧:

  1. 在gnuplot程序中:plot“/dev/stdin”...

  2. 在命令行中:gnuplot program.plot < data.dat


12
这个问题已经有了很好的回答,但我认为我可以在这里找到一个可以填补的空缺,即使只是减轻像我一样通过谷歌搜索来解决此问题的人的工作量。vagoberto的答案给了我解决我的问题所需的东西,因此我将在这里分享我的解决方案。
我在最新环境中开发了一个情节脚本,它让我能够做到:
#!/usr/bin/gnuplot -c 
set terminal png truecolor transparent crop
set output ARG1
set size 1, 0.2
rrLower = ARG2
rrUpper = ARG3
rrSD = ARG4
resultx = ARG5+0 # Type coercion required for data series
resulty = 0.02 # fixed
# etc.

这个命令可以在拥有最新的gnuplot环境(例如我的情况是5.0.3)的命令行中完美执行。

$ ./plotStuff.gp 'output.png' 2.3 6.7 4.3 7

当我把它上传到服务器并执行时,由于服务器版本是4.6.4(Ubuntu 14.04 LTS上的当前版本),导致执行失败。 下面的"shim"解决了这个问题,而不需要对原始脚本进行任何更改。

#!/bin/bash
# GPlot v<4.6.6 doesn't support direct command line arguments.
#This script backfills the functionality transparently.
SCRIPT="plotStuff.gp"
ARG1=$1
ARG2=$2
ARG3=$3
ARG4=$4
ARG5=$5
ARG6=$6

gnuplot -e "ARG1='${ARG1}'; ARG2='${ARG2}'; ARG3='${ARG3}'; ARG4='${ARG4}'; ARG5='${ARG5}'; ARG6='${ARG6}'" $SCRIPT

这两个脚本的组合允许在基本上任何*nix系统中,无论gnuplot版本如何,将参数从bash传递到gnuplot脚本中,同时保留HTML标签。

6

@vagoberto的回答在我看来似乎是最好的如果你需要位置参数,而我有一个小改进要添加。

@vagoberto的建议:

#!/usr/local/bin/gnuplot --persist

THIRD=ARG3
print "script name        : ", ARG0
print "first argument     : ", ARG1
print "third argument     : ", THIRD 
print "number of arguments: ", ARGC 

被以下所调用:

$ gnuplot -c script.gp one two three four five
script name        : script.gp
first argument     : one
third argument     : three
number of arguments: 5

对于像我这样的懒惰打字者,可以将脚本设置为可执行文件(chmod 755 script.gp

然后使用以下命令:

#!/usr/bin/env gnuplot -c

THIRD=ARG3
print "script name        : ", ARG0
print "first argument     : ", ARG1
print "third argument     : ", THIRD
print "number of arguments: ", ARGC

并将其执行为:

$ ./imb.plot a b c d
script name        : ./imb.plot
first argument     : a
third argument     : c
number of arguments: 4

5
你甚至可以运用一些shell魔法,例如像这样:
#!/bin/bash
inputfile="${1}" #you could even do some getopt magic here...

################################################################################
## generate a gnuplotscript, strip off bash header
gnuplotscript=$(mktemp /tmp/gnuplot_cmd_$(basename "${0}").XXXXXX.gnuplot)

firstline=$(grep -m 1 -n "^#!/usr/bin/gnuplot" "${0}")
firstline=${firstline%%:*} #remove everything after the colon
sed -e "1,${firstline}d" < "${0}" > "${gnuplotscript}"


################################################################################
## run gnuplot
/usr/bin/gnuplot -e "inputfile=\"${inputfile}\"" "${gnuplotscript}"
status=$?
if [[ ${status} -ne 0 ]] ; then
  echo "ERROR: gnuplot returned with exit status $?"
fi

################################################################################
## cleanup and exit
rm -f "${gnuplotscript}"
exit ${status}

#!/usr/bin/gnuplot
plot inputfile using 1:4 with linespoints
#... or whatever you want

我的实现略微复杂(例如,在sed调用中替换一些神奇的令牌,当然我已经做到了……),但为了更好地理解,我简化了这个示例。

你甚至可以让它变得更简单……但结果可能会有所不同。


5
在shell中输入
gnuplot -persist -e "plot filename1.dat,filename2.dat"

依次输入您想要的文件名。 -persist 用于使 gnuplot 屏幕保持在用户手动退出之前。


在Win7控制台中,选项-persist似乎不起作用?例如,gnuplot -persist -c "myscript.plt" "mydata.csv" "myoutput.png",这个命令可以正常工作,并且我按预期得到了文件“myoutput.png”,但是gnuplot屏幕没有出现(myscript.plt中没有exit命令)。为什么?如何使gnuplot屏幕在我的示例中显示? - lyl

1
另一种方法是这样的:
您有一个名为 scriptname.gp 的 gnuplot 脚本:
#!/usr/bin/gnuplot -p
# This code is in the file 'scriptname.gp'
EPATH = $0
FILENAME = $1 

plot FILENAME

现在,您可以通过这个复杂的语法调用gnuplot脚本scriptname.gp:
echo "call \"scriptname.gp\" \"'.'\" \"'data.dat'\"" | gnuplot 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接