Làm thế nào để truyền đối số dòng lệnh cho gnuplot?


148

Tôi muốn sử dụng gnuplot để vẽ hình từ tệp dữ liệu, giả sử foo.data . Hiện tại, tôi đã mã hóa tên tệp dữ liệu trong tệp lệnh, giả sử foo.plt và chạy lệnh gnuplot foo.plgđể vẽ dữ liệu. Tuy nhiên, tôi muốn truyền tên tệp dữ liệu dưới dạng đối số lệnh, ví dụ: lệnh đang chạy gnuplot foo.plg foo.data. Làm cách nào để phân tích các đối số dòng lệnh trong tệp tập lệnh gnuplot? Cảm ơn.

Câu trả lời:


191

Bạn có thể nhập biến thông qua chuyển đổi -e

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

Trong foo.plg sau đó bạn có thể sử dụng biến đó

$ cat foo.plg 
plot filename
pause -1

Để làm cho "foo.plg" chung chung hơn một chút, hãy sử dụng một điều kiện:

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

Lưu ý rằng -ephải đặt trước tên tệp nếu không tệp sẽ chạy trước các -ecâu lệnh. Cụ thể, chạy một gnuplot shebang #!/usr/bin/env gnuplotvới ./foo.plg -e ...các đối số CLI sẽ bỏ qua việc sử dụng các đối số được cung cấp.


20
Điều này cũng có thể được sử dụng với ifđể cung cấp mặc định. if ! exists("filename") filename='default.data'
mgilson

10
Đối với những người vấp phải điều này ngay bây giờ, bình luận của mgilson và Gnuplot 4.6 patchlevel 3 yêu cầu if (!exists("filename")thay thế if ! exists("filename").
Sam Mussmann

Làm thế nào để làm điều tương tự trong các cửa sổ?
padawan

6
@Chong: Hoặc kết hợp chúng lại với nhau hoặc đưa ra từng -eđối số, ví dụ -e "filename='default.data'; foo='bar'"hoặc -e "filename='default.data'" -e "foo='bar"'.
Thor

1
Lưu ý: Các -e ...tùy chọn có để đặt trước tên tập tin. Thật vậy, từ man gnuplotchúng ta có thể đọc: -e"danh sách lệnh" thực thi các lệnh được yêu cầu trước khi tải tệp đầu vào tiếp theo . .
Hastur

57

Bạn có thể chuyển đối số cho tập lệnh gnuplot kể từ phiên bản 5.0, với cờ -c. Những lập luận này được truy cập thông qua các biến ARG0để ARG9, ARG0là kịch bản, và ARG1để ARG9biến chuỗi. Số lượng đối số được đưa ra bởi ARGC.

Ví dụ: tập lệnh sau ("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 

có thể được gọi là:

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

hoặc trong gnuplot như

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

Trong gnuplot 4.6.6 trở về trước, tồn tại một callcơ chế với cú pháp khác (hiện không dùng nữa). Những lập luận được sử dụng qua $#, $0, ..., $9. Ví dụ: tập lệnh tương tự ở trên trông giống như:

#!/usr/bin/gnuplot --persist

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

và nó được gọi trong gnuplot là (hãy nhớ, phiên bản <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

Lưu ý rằng không có biến cho tên tập lệnh, $0đối số đầu tiên cũng vậy và các biến được gọi trong dấu ngoặc kép. Không có cách nào để sử dụng điều này trực tiếp từ dòng lệnh, chỉ thông qua các thủ thuật như cách được đề xuất bởi @ con-fu-se.


Tôi đã cố gắng sử dụng -cchuyển đổi với một tập lệnh có chứa các dòng như plot 'data' using 0:($1/100). gnuplotchết với biểu thức không hợp lệ lỗi vì $1bị biến mất. Tôi sai ở đâu Lưu ý rằng không có -c, kịch bản chạy thành công.
lorcap

Tôi đã thử nghiệm nó bằng gnuplot 5.0cách thêm vào các ví dụ này một dòng như thế plot 'data' using 0:($1/100), và không hiểu những gì bạn nói. Sẽ rất hiếm, vì phiên bản này xác định các biến ARG0- ARG9và không $1- $9. Tôi giả sử bạn cũng có phiên bản 5.0 (phải không?), Vì -ccờ không được hỗ trợ bởi các phiên bản trước. Tôi sẽ cần phải xem một kịch bản tối thiểu để xem vấn đề thực sự ở đâu: /
vagoberto

Tôi đang chạy gnuplot 5.0 patchlevel 0theo cygwin . Tập lệnh một dòng print ARG1; plot 'data' using 0:($1/100)in chính xác giá trị được chuyển qua ARG1và sau đó thoát với biểu thức không hợp lệ lỗi chỉ vào dấu gạch chéo của print ARG1; plot 'data' using 0:(/100).
lorcap

27

Bạn cũng có thể truyền thông tin qua môi trường như được đề xuất ở đây . Ví dụ của Ismail Amin được lặp lại ở đây:

Trong vỏ:

export name=plot_data_file

Trong tập lệnh Gnuplot:

#! /usr/bin/gnuplot

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

6
Thay vì xuất, bạn có thể gõ name=plot_data_file ./the_gnuplot_script.
Edgar Bonet

@Edgar Bonet: Phiên bản gnuplot nào là bắt buộc cho việc này? Nó dường như không hoạt động trên máy y sử dụng 4.2 ...
Bjoern

Xin chào @Bjoern! Tôi đang sử dụng Gnuplot 4.6, nhưng đây không phải là tính năng của Gnuplot, đây là một tính năng của trình bao: name=value commandbảo trình bao chạy lệnh với biến cụ thể đó trong môi trường của nó. Tôi đang sử dụng bash 4.3.11, nhưng tôi tin rằng đó là một tính năng shell rất phổ biến.
Edgar Bonet

23

Câu trả lời của Jari Laamanen là giải pháp tốt nhất. Tôi chỉ muốn giải thích cách sử dụng nhiều hơn 1 tham số đầu vào với các biến shell:

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

và foo.plg:

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

Như bạn có thể thấy, nhiều tham số được truyền bằng dấu hai chấm (như trong tập lệnh bash), nhưng các biến chuỗi CẦN phải được gói gọn với '' (cú pháp gnuplot, cú pháp KHÔNG Bash)


1
Đối với gnuplot, nó không thành vấn đề nếu bạn sử dụng 'hoặc "cho chuỗi. Các trích dẫn bên ngoài xung quanh -eđối số phải được "thay thế các biến bash. Sau đây cũng hoạt động tốt:OUTPUT=foobar; gnuplot -e "output=\"$OUTPUT\"; print output"
Christoph

Cảm ơn vì đã xác nhận rằng tôi có thể sử dụng dấu hai chấm để phân chia các lệnh. Không có câu trả lời nào khác cho thấy điều này.
tommy.carstensen 20/2/2015

14

Bạn có thể sử dụng thủ thuật trong môi trường unix / linux:

  1. trong chương trình gnuplot: cốt truyện "/ dev / stdin" ...

  2. Trong dòng lệnh: gnuplot chương trình.plot <data.dat


12

Câu hỏi này đã được trả lời tốt nhưng tôi nghĩ rằng tôi có thể tìm thấy một chỗ thích hợp để điền vào đây bất kể, nếu chỉ để giảm khối lượng công việc cho ai đó googling điều này như tôi đã làm. Câu trả lời từ vagoberto đã cho tôi những gì tôi cần để giải quyết phiên bản của vấn đề này và vì vậy tôi sẽ chia sẻ giải pháp của mình tại đây.

Tôi đã phát triển một kịch bản cốt truyện trong một môi trường cập nhật cho phép tôi làm:

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

Điều này thực hiện hoàn toàn tốt từ dòng lệnh trong một môi trường với một gnuplot gần đây (5.0.3 trong trường hợp của tôi).

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

Khi được tải lên máy chủ của tôi và thực thi, nó đã thất bại vì phiên bản máy chủ là 4.6.4 (hiện tại trên Ubuntu 14.04 LTS). Shim dưới đây đã giải quyết vấn đề này mà không yêu cầu bất kỳ thay đổi nào đối với tập lệnh gốc.

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

Sự kết hợp của hai tập lệnh này cho phép các tham số được truyền từ bash sang tập lệnh gnuplot mà không liên quan đến phiên bản gnuplot và về cơ bản là bất kỳ * nix nào.


5

Bạn thậm chí có thể làm một số phép thuật vỏ, ví dụ như thế này:

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

Việc triển khai của tôi phức tạp hơn một chút (ví dụ: thay thế một số mã thông báo ma thuật trong cuộc gọi sed, trong khi tôi đã sử dụng nó ...), nhưng tôi đã đơn giản hóa ví dụ này để hiểu rõ hơn. Bạn cũng có thể làm cho nó đơn giản hơn nữa .... YMMV.


4

Trong vỏ viết

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

và liên tiếp các tập tin bạn muốn. -persist được sử dụng để làm cho màn hình gnuplot duy trì miễn là người dùng không thoát nó bằng tay.


Trong giao diện điều khiển Win7, tùy chọn -persist dường như không hoạt động? Ví dụ: gnuplot -persist -c "myscript.plt" "mydata.csv" "myoutput.png"lệnh này hoạt động tốt và tôi nhận được tệp "myoutput.png" như tôi mong đợi, nhưng màn hình gnuplot không xuất hiện ( exitlệnh NO trong myscript.plt). Tại sao? Và làm thế nào để làm cho màn hình gnuplot hiển thị trong ví dụ của tôi?
LYL

1

Một cách khác là thế này:

Bạn có một tập lệnh gnuplot có tên scriptname.gp:

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

plot FILENAME

Bây giờ bạn có thể gọi tập lệnh gnuplot scriptname.gpbằng cú pháp hòa bình phức tạp này:

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

0

Câu trả lời của @ vagoberto có vẻ là IMHO tốt nhất nếu bạn cần các đối số vị trí và tôi có một cải tiến nhỏ để thêm vào.

đề nghị của 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 

được gọi bởi:

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

đối với những người đánh máy lười biếng như tôi, người ta có thể làm cho tập lệnh thực thi ( chmod 755 script.gp)

sau đó sử dụng như sau:

#!/usr/bin/env gnuplot -c

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

và thực hiện nó như:

$ ./imb.plot a b c d
script name        : ./imb.plot
first argument     : a
third argument     : c
number of arguments: 4
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.