您似乎以一种奇怪的方式混合了 bash 和 gnuplot。使用 bash 脚本尝试使用插入的变量动态生成 gnuplot 脚本是一种快速迷惑自己的方法。它也使阅读和调试变得困难。很容易忘记 bash 正在评估什么以及 gnuplot 正在评估什么。
当我看到你的第一行
ArrLength=${#arr[@]} #Get the length of array
我可以看到这是 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 评估为 something(如果尚未定义,则为空字符串)。您不能期望 gnuplot 变量 p 被用作 ${arr[$p]} 的 bash 评估中的索引,然后以某种方式为 gnuplot 循环的每次迭代生成不同的字符串。
总之,你写的不是gnuplot语法,也不是一个最小而完整的bash脚本。目前尚不清楚您打算如何将 bash 和 gnuplot 像这样组合在一起,但似乎您将它们结合得太紧了。
我的建议是编写一个 bash 脚本 并编写一个 gnuplot 脚本(作为单独的文件)。 Gnuplot 有自己的流程控制、迭代循环和变量评估。你可以为你需要它做的所有事情的一般情况编写一个独立的 gnuplot 脚本,然后在你的 bash 脚本的命令行上给出它的细节。
例如,您的子目录似乎都是 10 的倍数,并且总是从 10 开始。唯一可变的方面是有多少(最后一个是什么)。假设最后一个值以某种方式存储在 gnuplot 变量 last 中。另外,假设我们还以某种方式在outputdir 中拥有基本输出目录:
(在 gnuplot 脚本中,命名为 plot.gp):
plot for [p=10:last:10] sprintf("%s/%d/values.csv", outputdir, p) with lines title sprintf("%d", p)
for [p=10:last:10] 表示从 10 迭代到 last(含),每次迭代增加 10。第一个sprintf() 函数(如C)使用outputdir 和p(两者都是gnuplot 中的变量)构建一个字符串。 using 1:2 不是必需的,因为前两列是使用 with lines 的默认列,但如果您想明确说明,可以包含它们。第二个sprintf() 从迭代变量p 构建一个标题字符串。
现在,这假设 outputdir 和 last 具有有意义的值。当您在命令行上调用 gnuplot 时,您可以从 bash 脚本中分配这些值:
(在 bash 脚本中,调用 gnuplot 脚本)
gnuplot -e "last=40" -e "outputdir=\"$outputdir\"" plot.gp
-e 选项告诉 gnuplot 在运行文件plot.gp 中的脚本之前评估给定的字符串。在此示例中,gnuplot 变量 last 的值将是 40,而 gnuplot 变量 outputdir 将具有 bash 评估 $outputdir 的任何值。注意双引号内的转义双引号。外面的双引号是为了让 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 或更高版本,你应该可以使用negative index:
gnuplot -e "last=${arr[-1]};outputdir=\"$outputdir\"" plot.gp
请注意,数组变量的使用周围没有转义引号。预计它将评估为整数(40、90 等),我们希望将 last 分配给整数,而不是像 outputdir 这样的字符串。
如果这个字符串看起来很复杂,请尝试像这样考虑整个脚本。很容易对 bash 在做什么以及 gnuplot 在做什么感到困惑。
总而言之,写一个 bash 脚本和一个 单独的 gnuplot 脚本。 Gnuplot 能够处理一般情况。从 bash 开始,只需即时给出一些细节,不要试图动态生成整个脚本。它确实让事情变得更简单。