Bash gnuplot使用数组打印多个文件

Bash gnuplot使用数组打印多个文件,bash,gnuplot,Bash,Gnuplot,我需要用bash脚本在一个绘图中绘制多个文件。我可以通过在绘图功能ie中手动说明文件的位置来进行管理 plot "$outputdir/10/values.csv" using 1:2 with lines title "10", \ "$outputdir/20/values.csv" using 1:2 with lines title "20", \ "$outputdir/30/values.csv" using 1:2 with lines title "30" 这将在一个绘图中打印

我需要用bash脚本在一个绘图中绘制多个文件。我可以通过在绘图功能ie中手动说明文件的位置来进行管理

plot "$outputdir/10/values.csv" using 1:2 with lines title "10", \
"$outputdir/20/values.csv" using 1:2 with lines title "20", \
"$outputdir/30/values.csv" using 1:2 with lines title "30"
这将在一个绘图中打印所有三个值文件。但是我有一个动态数组,它根据假设得到的值的多少而变化。让我们假设数组arr看起来像这样

arr=(10 20 30 40)
#Sometimes arr has more values ex; arr=(10 20 30 40 50 60 70 80)
#arr corresponds to folders that will be created
#And will contain a values.csv file that I want to plot
如果不手动更改绘图代码,则不会打印40/values.csv

我目前试图修复的是gnuplot中的for循环

#The array arr is dynamically generated in another function
#Varies in size as example above

ArrLength=${#arr[@]} #Get the length of array
plot for [p=0:$ArrLength] "$outputdir/${arr[$p]}/values.csv" using 1:2 with lines title "${arr[$p]}"
打印时没有出现错误,但在“打印”中只打印一个值,这是数组中的第一个值,即它只打印$outputdir/10/values.csv

我尝试设置p=0:4来打印前五个文件,但它仍然只打印第一个文件。上面的for循环有什么问题


致以最诚挚的问候

您似乎以一种奇怪的方式混合了bash和gnuplot。使用bash脚本尝试动态生成带有插入变量的gnuplot脚本,这是一种让您感到困惑的快速方法。这也使得读取和调试变得困难。很容易忘记bash在评估什么,gnuplot在评估什么

当我看到你的第一行

ArrLength=${arr[@]}获取数组的长度
我可以看出这是bash代码,因为gnuplot将解释以第一个
开头的注释。(这也是bash对数组的语法,而不是gnuplot的)。美元符号
$
在gnuplot中有不同的含义。不是标记变量标识符,
$
是一个列号运算符(
$2
是第2列,
$i
是第i列,等等)。看看这条线

plot for [p=0:$ArrLength] "$outputdir/${arr[$p]}/values.csv" using 1:2 with lines title "${arr[$p]}"
这显然是一行bash语法,显然是在试图编写一行gnuplot的字符串中。Bash将计算变量
$ArrLength
$outputdir
${arr[$p]}
,并用它们的值的一些字符串替换它们。还要记住,
p
是gnuplot中的变量,而不是bash中的变量。Bash将把
$p
计算为某物(如果尚未定义,则为空字符串)。您不能期望gnuplot变量
p
${arr[$p]}
的bash计算中用作索引,然后以某种方式为gnuplot循环的每次迭代生成不同的字符串

简而言之,您所编写的不是gnuplot语法,它也不是一个最小且完整的bash脚本。目前还不清楚您打算如何将bash和gnuplot这样组合在一起,但似乎您将它们结合得太紧密了


我的建议是编写一个bash脚本,并编写一个gnuplot脚本(作为单独的文件)。Gnuplot有自己的流控制、迭代循环和变量求值。您可以编写一个自包含的gnuplot脚本,用于一般情况下需要它执行的所有操作,然后在bash脚本的命令行中为它提供详细信息

例如,您的子目录似乎都是10的倍数,并且总是以10开头。唯一可变的方面是有多少(最后一个是什么)。假设最后一个值以某种方式存储在gnuplot变量
last
中。另外,假设我们在
outputdir
中也有基本输出目录:

(在gnuplot脚本中,名为
plot.gp
):

[p=10:last:10]的
意味着从10迭代到
last
(含),每次迭代加10。第一个
sprintf()
函数(类似于C)使用
outputdir
p
构建一个字符串(两者都是gnuplot中的变量)。使用1:2的
是不必要的,因为前两列是使用
和行的默认列
,但如果您希望明确,可以将它们包括在内。第二个
sprintf()
从迭代变量
p
构建一个标题字符串

现在,假设
outputdir
last
具有有意义的值。在命令行上调用gnuplot时,可以从bash脚本中分配这些值:

(在bash脚本中,调用gnuplot脚本)

-e
选项告诉gnuplot在运行文件
plot.gp
中的脚本之前对给定字符串求值。在本例中,gnuplot变量
last
的值为40,gnuplot变量
outputdir
的值为bash计算出的值。请注意双引号中的转义双引号。外部双引号允许bash计算字符串内的变量(
$outputdir
需要由bash计算)。内部(转义)引号用于在gnuplot代码中分隔字符串。例如,如果bash将
$outputdir
计算为
data
,那么gnuplot将看到
outputdir=“data”
,这是字符串对变量
outputdir
的有效gnuplot赋值。如果需要,您可以将这两个
-e
选项组合为一个:

gnuplot -e "last=40;outputdir=\"$outputdir\"" plot.gp
您可能希望在bash中使用数组中的
last
值,而不是像这样硬编码。所以在实践中,它看起来更像

gnuplot -e "last=${arr[${#arr[@]}-1]};outputdir=\"$outputdir\"" plot.gp
或者,如果您有bash 4.3或更高版本,您应该能够使用:

请注意,数组变量的使用没有转义引号。预计它将计算为整数(
40
90
,等等),我们希望将
last
分配给整数,而不是像
outputdir
这样的字符串

如果这一个字符串看起来很复杂,试着像这样思考整个脚本。很容易混淆bash在做什么和gnuplot在做什么

总之,编写一个bash脚本和一个单独的gnuplot脚本。Gnuplot能够处理一般cas
gnuplot -e "last=40;outputdir=\"$outputdir\"" plot.gp
gnuplot -e "last=${arr[${#arr[@]}-1]};outputdir=\"$outputdir\"" plot.gp
gnuplot -e "last=${arr[-1]};outputdir=\"$outputdir\"" plot.gp