Como passar o argumento da linha de comando para o gnuplot?

148

Eu quero usar o gnuplot para desenhar figuras do arquivo de dados, digamos foo.data . Atualmente, codifiquei o nome do arquivo de dados no arquivo de comando, digamos foo.plt , e executei o comando gnuplot foo.plgpara plotar dados. No entanto, quero passar o nome do arquivo de dados como um argumento de comando, por exemplo, executando o comando gnuplot foo.plg foo.data. Como analisar os argumentos da linha de comando no arquivo de script gnuplot? Obrigado.

Yun Huang
fonte

Respostas:

191

Você pode inserir variáveis ​​via switch -e

$ gnuplot -e "filename='foo.data'" foo.plg

Em foo.plg, você pode usar essa variável

$ cat foo.plg 
plot filename
pause -1

Para tornar o "foo.plg" um pouco mais genérico, use uma condição:

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

Observe que -edeve preceder o nome do arquivo, caso contrário, o arquivo será executado antes das -einstruções. Em particular, a execução de um gnuplot shebang #!/usr/bin/env gnuplotcom ./foo.plg -e ...argumentos da CLI ignorará o uso dos argumentos fornecidos.

Jari Laamanen
fonte
20
Isso também pode ser usado ifpara fornecer padrões. if ! exists("filename") filename='default.data'
mgilson
10
Para as pessoas que se deparam com isso agora, o comentário de mgilson e o nível de patch 3 do Gnuplot 4.6 exigem em if (!exists("filename")vez de if ! exists("filename").
Sam Mussmann
Como fazer a mesma coisa no Windows?
usar o seguinte
6
@Chong: Separe-os ou dê a cada um em um -eargumento, por exemplo, -e "filename='default.data'; foo='bar'"ou -e "filename='default.data'" -e "foo='bar"'.
Thor
1
Nota: A -e ...opção precisa preceder o nome do arquivo. De fato man gnuplot, podemos ler: -e"lista de comandos" executa os comandos solicitados antes de carregar o próximo arquivo de entrada . .
Hastur
57

Você pode passar argumentos para um script gnuplot desde a versão 5.0, com a flag -c. Esses argumentos são acessados ​​pelas variáveis ARG0para ARG9, ARG0sendo o script e ARG1para ARG9variáveis ​​de cadeia. O número de argumentos é dado por ARGC.

Por exemplo, o seguinte script ("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 

pode ser chamado como:

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

ou dentro do gnuplot como

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

No gnuplot 4.6.6 e versões anteriores, existe um callmecanismo com uma sintaxe diferente (agora obsoleta). Os argumentos são acessados através $#, $0, ..., $9. Por exemplo, o mesmo script acima se parece com:

#!/usr/bin/gnuplot --persist

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

e é chamado dentro do gnuplot como (lembre-se, versão <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

Observe que não há variável para o nome do script, assim $0como o primeiro argumento, e as variáveis ​​são chamadas entre aspas. Não há como usar isso diretamente da linha de comando, apenas através de truques como o sugerido por @ con-fu-se.

vagoberto
fonte
Eu tentei usar o -cswitch com um script que contém linhas como plot 'data' using 0:($1/100). gnuplotmorre com o erro expressão inválida porque $1desapareceu. Onde eu estou errado? Observe que -c, sem , o script é executado com êxito.
Lorcap # 30/15
Eu testei gnuplot 5.0adicionando a esses exemplos uma linha como plot 'data' using 0:($1/100), e não entendi o que você diz. Seria raro, já que esta versão define as variáveis ARG0- ARG9e não $1- $9. Presumo que você também tenha a versão 5.0 (não é?), Pois o -csinalizador não é suportado por versões anteriores. Eu precisaria ver um roteiro mínimo para ver onde está o problema real: /
vagoberto
Estou correndo gnuplot 5.0 patchlevel 0sob o cygwin . O script de uma linha print ARG1; plot 'data' using 0:($1/100)imprime corretamente o valor passado como ARG1e sai com a expressão inválida de erro apontando para a barra de print ARG1; plot 'data' using 0:(/100).
Lorcap #
27

Você também pode passar informações pelo ambiente, conforme sugerido aqui . O exemplo de Ismail Amin é repetido aqui:

No shell:

export name=plot_data_file

Em um script Gnuplot:

#! /usr/bin/gnuplot

name=system("echo $name")
set title name
plot name using ($16 * 8):20 with linespoints notitle
pause -1
Thor
fonte
6
Em vez de exportar, você pode digitar name=plot_data_file ./the_gnuplot_script.
Edgar Bonet
@ Edgar Bonet: Qual versão do gnuplot é necessária para isso? Ele não parecem funcionar na máquina y que utiliza 4.2 ...
Bjoern
Olá @Bjoern! Estou usando o Gnuplot 4.6, mas este não é um recurso do Gnuplot, é um recurso do shell: name=value commanddiz ao shell para executar o comando com essa variável específica em seu ambiente. Estou usando o bash 4.3.11, mas acredito que é um recurso de shell muito comum.
Edgar Bonet
23

A resposta de Jari Laamanen é a melhor solução. Quero apenas explicar como usar mais de 1 parâmetro de entrada com variáveis ​​de shell:

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

e foo.plg:

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

Como você pode ver, mais parâmetros são passados ​​com ponto-e-vírgula (como nos scripts bash), mas as variáveis ​​de string precisam ser encapsuladas com '' (sintaxe gnuplot, sintaxe NOT Bash)

Mo3bius
fonte
1
Para o próprio gnuplot, não importa se você usa 'ou "para strings. As aspas externas ao redor do -eargumento devem ser "para que as variáveis ​​bash sejam substituídas. O seguinte também funciona bem:OUTPUT=foobar; gnuplot -e "output=\"$OUTPUT\"; print output"
Christoph
Obrigado por confirmar que posso usar ponto e vírgula para dividir comandos. Nenhuma das outras respostas mostra isso.
21415 Tommy.carstensen
14

Você pode usar truques no ambiente unix / linux:

  1. no programa gnuplot: plot "/ dev / stdin" ...

  2. Na linha de comando: gnuplot program.plot <data.dat

arto
fonte
12

Esta pergunta está bem respondida, mas acho que posso encontrar um nicho para preencher aqui, independentemente, apenas para reduzir a carga de trabalho em alguém pesquisando isso no Google, como eu fiz. A resposta do vagoberto me deu o que eu precisava para resolver minha versão deste problema e, portanto, vou compartilhar minha solução aqui.

Desenvolvi um script de plotagem em um ambiente atualizado, o que me permitiu:

#!/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.

Isso executa perfeitamente bem da linha de comando em um ambiente com um gnuplot recente (5.0.3 no meu caso).

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

Quando carregado no meu servidor e executado, ele falhou porque a versão do servidor era 4.6.4 (atual no Ubuntu 14.04 LTS). O calço abaixo resolveu esse problema sem exigir nenhuma alteração no script original.

#!/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

A combinação desses dois scripts permite que os parâmetros sejam transmitidos dos scripts bash para gnuplot sem levar em consideração a versão do gnuplot e basicamente qualquer * nix.

bp.
fonte
5

Você pode até fazer alguma mágica de shell, por exemplo:

#!/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

Minha implementação é um pouco mais complexa (por exemplo, substituindo alguns tokens mágicos na chamada sed, enquanto eu já estou nela ...), mas simplifiquei este exemplo para entender melhor. Você também pode torná-lo ainda mais simples ... YMMV.

Stefan
fonte
4

No shell, escreva

gnuplot -persist -e "plot filename1.dat,filename2.dat"

e consecutivamente os arquivos que você deseja. -persist é usado para fazer a tela do gnuplot permanecer enquanto o usuário não sair dela manualmente.

Aniruddha Bera
fonte
No console Win7, a opção -persist parece não funcionar? Por exemplo, gnuplot -persist -c "myscript.plt" "mydata.csv" "myoutput.png"esse comando funciona bem e eu recebo o arquivo "myoutput.png" conforme o esperado, mas a tela do gnuplot não aparece ( exitcomando NO no myscript.plt). Por quê? E como fazer a tela do gnuplot aparecer no meu exemplo?
Lyl
1

Ainda outra maneira é esta:

Você tem um script gnuplot chamado scriptname.gp:

#!/usr/bin/gnuplot -p
# This code is in the file 'scriptname.gp'
EPATH = $0
FILENAME = $1 

plot FILENAME

Agora você pode chamar o script gnuplot scriptname.gpcom esta paz de sintaxe complicada:

echo "call \"scriptname.gp\" \"'.'\" \"'data.dat'\"" | gnuplot 
confundir
fonte
0

A resposta de @ vagoberto parece a melhor IMHO se você precisar de argumentos posicionais , e eu tenho uma pequena melhoria a acrescentar.

sugestão de 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 

chamado por:

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

para aqueles tipógrafos preguiçosos como eu, é possível tornar o script executável ( chmod 755 script.gp)

depois use o seguinte:

#!/usr/bin/env gnuplot -c

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

e execute-o como:

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