【问题标题】:Scripting with gnuplot--where sed使用 gnuplot 编写脚本--where sed
【发布时间】:2012-08-26 18:27:25
【问题描述】:

所以我正在寻找一些快速而肮脏的解决方案。

问题:

我正在尝试使用 gnuplot 绘制数据文件的特定部分。这可以。基本行类似于

plot "<(sed -n '1,100p' pointsandstuff.dat)" u 1:log($4**2+$5**2) notitle

这很好用。我想要的下一步是在我的标题中包含数据的另一部分,即数据条目 $3(列出的点是相同的,所以我可以从任何地方解析它)。我遇到了问题,因为虽然情节看起来不错,但我似乎无法将正则表达式信息输入“标题”。一个不起作用的例子”

plot "<(sed -n '1,100p' pointsandstuff.dat)" u 1:log($4**2+$5**2) title "<(sed -n '1,1p' pointsandstuff.dat)"

(理论上,这会吐出一整条数据线,但实际上我只是得到标题“

我尝试使用 bash 脚本对此进行攻击,但是我使用的 '$' 使 bash 脚本变得混乱:

#!/bin/bash


STRING=$(echo|sed -n '25001,25001p' pointsandstuff.dat)
echo $STRING


 gnuplot -persist << EOF
 set xrange[:] noreverse nowriteback
 set yrange[:] noreverse nowriteback

 eval "plot "<(sed -n '25001,30000p' pointsandstuff.dat)" u 1:log($4**2+$5**2) title $STRING


EOF

Bash 不知道如何处理“$4”和“$5”。

【问题讨论】:

    标签: bash scripting sed gnuplot


    【解决方案1】:

    啊哈,谢谢大家。现在已经提出了一些解决方案——最简单的就是从以前的那些 $s 中转义(我错误地认为 gnuplot 不喜欢......)。对白衣:

    STRING=$(echo|sed -n '1,1p' spointsandstuff.dat)
    echo $STRING
    
    
     gnuplot -persist << EOF
     set xrange[:] noreverse nowriteback
     set yrange[:] noreverse nowriteback
    
     eval "plot "<(sed -n '1,100p' pointsandstuff.dat)" u 1:(log(\$4**2+\$5**2)) title '$STRING'
     !gv diag_spec.eps &
    
    EOF
    

    不过,谢谢大家——这是玩这些东西的一个很好的借口……在这里希望,如果以后有任何可怜的灵魂看到这个脚本,他们可能会更容易一些。

    【讨论】:

      【解决方案2】:

      我对这个问题的理解有点模糊,但看起来你想绘制前 100 行——这很容易做到:

      plot '< head -100 datafile.dat' u  ....
      

      当然,如果您愿意,您可以使用sed(或awk 或...)。仅 gnuplot 的解决方案可能如下所示:

      plot 'datafile.dat' u ($0 > 100? 1/0:$1):(log($4**2+$5**2))
      

      或者像这样(对于常规选择更简单):

      plot 'datafile.dat' every ::25001::30000 u 1:(log($4**2+$5**2)
      

      并在another answer 中进行了更详细的解释。

      现在,如果您希望标题来自数据文件,可以使用 gnuplot 的 backtic substitution 解析出来:

      plot ... title "`head -1 datafile.dat | awk '{print $3}'`"
      

      这与gnuplot的系统命令基本相同:

      plot ... title system("head -1 datafile.dat | awk '{print $3}'")
      

      但在这种情况下,您可能可以使用columnhead函数:

      plot ... title columnhead(3)
      

      【讨论】:

        【解决方案3】:

        您似乎正在尝试进程替换,但双引号在第一种情况下会阻止它工作,而在第二种情况下您需要命令替换。

        你有:

        plot "<(sed -n '1,100p' pointsandstuff.dat)" u 1:log($4**2+$5**2) \
              title "<(sed -n '1,1p' pointsandstuff.dat)"
        

        你需要:

        plot <(sed -n '1,100p' pointsandstuff.dat) u 1:log($4**2+$5**2) \
              title "$(sed -n '1,1p' pointsandstuff.dat)"
        

        第二种情况下的双引号可能不是绝对必要的,但它们的存在不会出错。

        • 进程替换生成一个文件名并将嵌套命令的输出提供给该文件;该命令认为它正在读取文件(因为它正在读取文件)。

        • 命令替换将嵌套命令的输出捕获在字符串中,并将该字符串传递给命令(当它用作命令的参数时,如此处)。

        【讨论】:

        • 谢谢乔纳森!但似乎 gnuplot(通过此 EOF 块通过管道传输)不会将第一个 sed 短语评估为字符串(即,如果您去掉双引号,它会给出错误)。就好像 gnuplot 中的 plot 命令有一些类似于 eval 的行为。
        • 突然想到的一件事是,在 gnuplot 管道块之外进行所有数据操作可能更明智。有没有办法在不重写一堆数据文件的情况下做到这一点(即,一种以 gnuplot 友好的方式在 gnuplot 管道块之外操作数据而无需写入磁盘的方法?)
        • 对于调试,如果你有单独的步骤会更容易。例如,title=$(sed 1q pointsandstuff.dat) 允许您在将$title 提供给plot 之前打印它。 (使用1q 代替-n 1p 意味着sed 不会读取整个文件,如果文件很大,这可以提高性能。)您可能需要查看1:log($4**2+$5**2) 参数周围的单引号,因为没有引号,shell 将扩展 $4$5(很可能是空字符串)。
        • 我没有查看plot 的参数约定,但可能有一种方法,例如sed 100q pointsandstuff.dat | plot - u '1:log($4**2+$5**2)' title "$title",可以将sed 的输出提供给plot,而不使用管道使用进程重定向。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 2018-03-04
        • 2016-09-04
        • 2011-09-04
        • 1970-01-01
        相关资源
        最近更新 更多