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.

Yun Huang
źródło

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.

Jari Laamanen
źródło
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.

vagoberto
źródło
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
Thor
źródło
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)

Mo3bius
źródło
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

arto
źródło
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.

bp.
źródło
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.

Stefan
źródło
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.

Aniruddha Bera
źródło
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 
dezorientować
źródło
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
Brett Holman
źródło