0

我正在尝试使用set for cycle命令为 gnuplot 环境设置变量。我使用的是 4.6 版本,根据gnuplot 文档(第 70 页),语法如下:

for [intvar = start:end{:increment}]
for [stringvar in "A B C D"]
Examples:
set for [i = 1:10] style line i lc rgb "blue"

但我得到这个错误:

gnuplot> set for [var in gpvars] replace(var,'#_#',' ')
                                 ^
         line 0: Unrecognized option.  See 'help set'.

我的脚本:

#!/bin/bash

OUTDIRNAME="out"
TIMEFORMAT='%d.%m.%y'
GPPARS=( "xlabel "Time"" "ylabel "value1"" "y2label "value2"" "format x "%H:%M"")
GPPARS_MOD=()

for (( i=0; i < ${#GPPARS[@]}; i++)); do 
  FILE=${GPPARS[${i}]}
  echo "arg=${FILE}"
  GPPARS_MOD+=( "`echo "${FILE}" | sed -e 's/ /#_#/g'`" )
done

gnuplot << EOF
reset

replace(S,C,R)=(strstrt(S,C)) ? \
    replace( S[:strstrt(S,C)-1].R.S[strstrt(S,C)+strlen(C):] ,C,R) : S

set terminal png
set output "${OUTDIRNAME}/graph.png"
set timefmt "${TIMEFORMAT}"
set xdata time

gpvars="${GPPARS_MOD[@]}"

set for [var in gpvars] {
   replace(var,'#_#',' ')
}

...

EOF

...

exit 0 

我也在使用函数替换,因为空格(gnuplot 忽略转义序列)该函数可以完美地用于循环绘图。我尝试过使用和不使用函数以及使用不带空格的变量,但结果是一样的。

4

1 回答 1

1

作为旁注——我不确定我是否相信你的 bash 数组会按照你想要的方式对事物进行分组......对我来说,你的报价被剥夺了。尝试:

GPPARS=( "xlabel 'Time'" "ylabel 'value1'" "y2label 'value2'" "format x '%H:%M'")

反而。(内部双引号替换为单引号)

这是一个棘手的问题——您使用 gnuplot 4.6 是一件好事,否则我不知道如何解决它。 (编辑——使用 gnuplot 4.4,您可以使用 、 、 、 和宏的组合wordwords但这ifreread一个exists相当混乱的解决方案)

请注意,您所拥有的内容不起作用,因为它类似于:

MYLABEL='xlabel "foo"'
set MYLABEL

Gnuplot 不会在执行 set 命令之前扩展 MYLABEL,以便您可以执行以下操作:

MYLABEL="totally cool X label here!"
set xlabel MYLABEL

你想要的可以使用宏来完成(但是唉,不是迭代):

set macro 
MYLABEL='xlabel "foo"'
set @MYLABEL

但这在这里也不起作用,因为宏扩展发生在其他任何事情之前(例如函数评估)。您在这里需要的是 gnuplot 在 4.6 中引入的更通用的迭代,并结合eval

do for [ var in gpvars ] {
    eval( 'set '.replace(var,'#_#',' ') )
}

编辑——gnuplot 4.2+ 解决方案

#top of script -- Nothing should go here.
replace(S,C,R)=(strstrt(S,C)) ? \
     replace( S[:strstrt(S,C)-1].R.S[strstrt(S,C)+strlen(C):] ,C,R) : S
if( ! exists("N") ) N=1
TODO="${GPPARS_MOD[@]}"
set macro
do_set=replace(word(TODO,N),'#_#',' ')
set @do_set
N=N+1
if( N <= words(TODO) ) reread
#rest of script here ...
于 2012-06-21T13:33:36.657 回答