Jak przekazać argument wiersza poleceń do gnuplot?


148

Chcę użyć gnuplot, aby narysować figurę z pliku danych, powiedzmy foo.data . Obecnie zakodowałem na stałe nazwę pliku danych w pliku poleceń, powiedzmy foo.plt i uruchomiłem polecenie, gnuplot foo.plgaby wykreślić dane. Chcę jednak przekazać nazwę pliku danych jako argument polecenia, np. Uruchomione polecenie gnuplot foo.plg foo.data. Jak przeanalizować argumenty wiersza poleceń w pliku skryptu gnuplot? Dzięki.

Odpowiedzi:


191

Możesz wprowadzać zmienne za pomocą przełącznika -e

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

W foo.plg możesz następnie użyć tej zmiennej

$ cat foo.plg 
plot filename
pause -1

Aby nieco bardziej uogólnić „foo.plg”, użyj warunku:

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

Zauważ, że -emusi poprzedzać nazwę pliku, w przeciwnym razie plik zostanie uruchomiony przed -einstrukcjami. W szczególności uruchomienie shebang gnuplot #!/usr/bin/env gnuplotz ./foo.plg -e ...argumentami CLI zignoruje użycie dostarczonych argumentów.


20
Można to również wykorzystać ifdo podania wartości domyślnych. if ! exists("filename") filename='default.data'
mgilson

10
Dla osób, które teraz się z tym natkną, if (!exists("filename")zamiast tego wymagają komentarza mgilsona i Gnuplot 4.6 patchlevel 3 if ! exists("filename").
Sam Mussmann,

Jak zrobić to samo w oknach?
padawan

6
@Chong: Połącz je ze sobą lub podaj w -eargumencie, np . -e "filename='default.data'; foo='bar'"Lub -e "filename='default.data'" -e "foo='bar"'.
Thor

1
Uwaga:-e ... opcja musi poprzedzać nazwę pliku. Rzeczywiście, z man gnuplottego możemy przeczytać: -e"lista poleceń" wykonuje żądane polecenia przed załadowaniem następnego pliku wejściowego . .
Hastur

57

Możesz przekazywać argumenty do skryptu gnuplot od wersji 5.0 za pomocą flagi -c. Dostęp do tych argumentów uzyskuje się poprzez zmienne ARG0do ARG9, ARG0będące skryptem, oraz ARG1do ARG9zmiennych łańcuchowych. Liczba argumentów jest podana przez ARGC.

Na przykład następujący skrypt („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 

można nazwać:

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

lub w gnuplot jako

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

W gnuplot 4.6.6 i wcześniejszych istnieje callmechanizm z inną (obecnie przestarzałą) składnią. Argumenty są dostępne za pośrednictwem $#, $0, ..., $9. Na przykład ten sam skrypt powyżej wygląda następująco:

#!/usr/bin/gnuplot --persist

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

i jest wywoływany w gnuplot jako (pamiętaj, wersja <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

Zauważ, że nie ma zmiennej dla nazwy skryptu, więc $0jest to pierwszy argument, a zmienne są wywoływane w cudzysłowach. Nie ma sposobu, aby użyć tego bezpośrednio z linii poleceń, tylko za pomocą sztuczek, jak sugeruje @ con-fu-se.


Próbowałem użyć -cprzełącznika ze skryptem zawierającym wiersze, takie jak plot 'data' using 0:($1/100). gnuplotumiera z błędem nieprawidłowe wyrażenie, ponieważ $1zniknął. Gdzie się mylę? Zauważ, że bez -ctego skrypt działa pomyślnie.
lorcap

Przetestowałem to z gnuplot 5.0, dodając do tych przykładów wiersz typu plot 'data' using 0:($1/100), i nie dostałem tego, co mówisz. Byłoby to rzadkie, ponieważ ta wersja definiuje zmienne ARG0- ARG9a nie $1- $9. Zakładam, że masz również wersję 5.0 (prawda?), Ponieważ -cflaga nie jest obsługiwana przez wcześniejsze wersje. Musiałbym zobaczyć minimalny skrypt, aby zobaczyć, gdzie jest prawdziwy problem: /
vagoberto

Biegnę gnuplot 5.0 patchlevel 0pod Cygwin . Jednowierszowy skrypt print ARG1; plot 'data' using 0:($1/100)poprawnie drukuje wartość przekazaną jako, ARG1a następnie kończy pracę z błędnym wyrażeniem wskazującym na ukośnik print ARG1; plot 'data' using 0:(/100).
lorcap

27

Możesz również przekazywać informacje poprzez środowisko, jak sugerowano tutaj . Przykład Ismaila Amina jest tu powtórzony:

W powłoce:

export name=plot_data_file

W skrypcie Gnuplot:

#! /usr/bin/gnuplot

name=system("echo $name")
set title name
plot name using ($16 * 8):20 with linespoints notitle
pause -1

6
Zamiast eksportować, możesz wpisać name=plot_data_file ./the_gnuplot_script.
Edgar Bonet

@Edgar Bonet: Która wersja gnuplot jest do tego potrzebna? Wygląda na to, że nie działa na maszynie y, która używa 4,2 ...
Bjoern

Cześć @Bjoern! Używam Gnuplot 4.6, ale to nie jest funkcja Gnuplot, jest to funkcja powłoki: name=value commandmówi powłoce, aby uruchomiła polecenie z tą konkretną zmienną w swoim środowisku. Używam basha 4.3.11, ale uważam, że jest to bardzo powszechna funkcja powłoki.
Edgar Bonet

23

Odpowiedź Jari Laamanena jest najlepszym rozwiązaniem. Chcę tylko wyjaśnić, jak używać więcej niż 1 parametru wejściowego ze zmiennymi powłoki:

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

i foo.plg:

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

Jak widać, więcej parametrów jest przekazywanych średnikami (jak w skryptach bash), ale zmienne łańcuchowe MUSZĄ być hermetyzowane za pomocą '' (składnia gnuplot, NOT Bash)


1
Dla samego gnuplot to nie ma znaczenia, jeśli używasz 'lub "ciągów. Zewnętrzne cudzysłowy wokół -eargumentu muszą oznaczać "podstawianie zmiennych bash. Następujące również działa dobrze:OUTPUT=foobar; gnuplot -e "output=\"$OUTPUT\"; print output"
Christoph

Dziękuję za potwierdzenie, że mogę używać średników do dzielenia poleceń. Żadna z pozostałych odpowiedzi tego nie pokazuje.
tommy.carstensen

14

Możesz użyć triku w środowisku unix / linux:

  1. w programie gnuplot: plot "/ dev / stdin" ...

  2. W linii poleceń: gnuplot program.plot <data.dat


12

Odpowiedź na to pytanie jest dobra, ale myślę, że mimo wszystko mogę znaleźć niszę do wypełnienia, choćby po to, aby zmniejszyć obciążenie pracą kogoś, kto szuka tego w Google, tak jak ja. Odpowiedź od vagoberto dała mi to, czego potrzebowałem, aby rozwiązać moją wersję tego problemu, więc podzielę się tutaj moim rozwiązaniem.

Napisałem skrypt fabularny w nowoczesnym środowisku, co pozwoliło mi na:

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

Działa to doskonale z wiersza poleceń w środowisku z niedawnym programem gnuplot (w moim przypadku 5.0.3).

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

Po przesłaniu na mój serwer i uruchomieniu nie powiodło się, ponieważ wersja serwera to 4.6.4 (aktualna na Ubuntu 14.04 LTS). Poniższa podkładka rozwiązała ten problem bez konieczności zmiany oryginalnego skryptu.

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

Połączenie tych dwóch skryptów umożliwia przekazywanie parametrów ze skryptów bash do skryptów gnuplot bez względu na wersję gnuplot iw zasadzie w każdym * nix.


5

Możesz nawet zrobić trochę magii muszli, na przykład w ten sposób:

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

Moja implementacja jest nieco bardziej złożona (np. Zastąpienie niektórych magicznych tokenów w wywołaniu seda, skoro już się tym zajmuję ...), ale uprościłem ten przykład dla lepszego zrozumienia. Możesz też to uprościć ... YMMV.


4

W powłoce napisz

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

i kolejno pliki, które chcesz. -persist służy do zatrzymania ekranu gnuplot tak długo, jak użytkownik nie wyjdzie z niego ręcznie.


W konsoli Win7 opcja -persist nie działa? Na przykład, gnuplot -persist -c "myscript.plt" "mydata.csv" "myoutput.png"to polecenie działa dobrze i otrzymuję plik „myoutput.png” zgodnie z oczekiwaniami, ale ekran gnuplot nie pojawia się (NIE exitpolecenie w myscript.plt). Czemu? A jak sprawić, by ekran gnuplot pokazał się w moim przykładzie?
lyl

1

Jeszcze inny sposób jest taki:

Masz skrypt gnuplot o nazwie scriptname.gp:

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

plot FILENAME

Teraz możesz wywołać skrypt gnuplot za scriptname.gppomocą tego zawiłego spokoju składni:

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

0

Odpowiedź @vagoberto wydaje się najlepsza IMHO, jeśli potrzebujesz argumentów pozycyjnych , i mam małe ulepszenie do dodania.

sugestia 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 

który jest wywoływany przez:

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

dla tych leniwych maszynistów, takich jak ja, można by uczynić skrypt wykonywalnym ( chmod 755 script.gp)

następnie użyj następującego:

#!/usr/bin/env gnuplot -c

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

i wykonaj to jako:

$ ./imb.plot a b c d
script name        : ./imb.plot
first argument     : a
third argument     : c
number of arguments: 4
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.