2012-04-24 38 views
22

Tôi muốn xác định chữ viết tắt đơn giản của cuộc gọi đến gs (ghostscript) qua tập lệnh trình bao. Đối số đầu tiên cung cấp tất cả các tệp cần được hợp nhất, tệp cuối cùng cung cấp tên của tệp đầu ra. Rõ ràng, những điều sau không hoạt động (chỉ để hiển thị mục tiêu):Làm thế nào để xác định một kịch bản shell với số lượng đối số biến?

#!/bin/sh 
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=$last $1 $2 ... 

Làm cách nào để thực hiện điều này?

Một thường sẽ gọi tập lệnh này qua myscript infile1.pdf infile2.pdf ... outfile.pdf hoặc myscript *.pdf outfile.pdf.

Trả lời

34

Biến bash [email protected]$* mở rộng vào danh sách đối số dòng lệnh. Nói chung, bạn sẽ muốn sử dụng "[email protected]" (nghĩa là, [email protected] được bao quanh bởi dấu ngoặc kép). Điều này sẽ làm điều đúng nếu ai đó vượt qua kịch bản của bạn một đối số có chứa khoảng trắng.

Vì vậy, nếu bạn đã có trong kịch bản của bạn:

outputfile=$1 
shift 
gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=$outputfile "[email protected]" 

Và bạn gọi là kịch bản của bạn như thế này:

myscript out.pdf foo.ps bar.ps "another file.ps" 

này sẽ mở rộng tới:

gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOUTPUTFILE=out.pdf foo.ps bar.ps "another file.ps" 

Đọc "Special Parameters" của trang bash để biết thêm thông tin.

+0

Cảm ơn larsks. Có thể có tên tệp đầu ra là đối số * cuối cùng * (không phải là đầu tiên) không? –

+0

Marius Hofert: Bạn không thể dễ dàng thay đổi yếu tố cuối cùng, vì vậy điều này phức tạp hơn một chút. Một cái gì đó như thế này: 'outputfile = $ {@: -1}; args = ("$ {@: 1: $ (($ {# @} - 1))}") '. Bạn nên chấp nhận câu trả lời của larsks này. – jordanm

+0

Bạn * có thể *, nhưng hơi xấu xí. Idelic có một ví dụ trong câu trả lời của anh ta. Bạn kết thúc với nhiều hơn nữa cruft trong mã của bạn. – larsks

18

Để vượt qua các tập tin đầu ra như là đối số cuối cùng, sử dụng một mảng:

ARGS=("[email protected]") 
# Get the last argument 
outputfile=${ARGS[-1]} 
# Drop it from the array 
unset ARGS[${#ARGS[@]}-1] 

exec gs ... -sOUTPUTFILE=$outputfile "${ARGS[@]}" 

Trước khi phiên bản 4, bash không cho phép subscript tiêu cực trong mảng (và sản xuất các báo cáo lỗi bởi Marius trong các ý kiến) , vì vậy nếu bạn đang sử dụng 3.x, bạn cần phải sử dụng nhiều uglier

outputfile=${ARGS[${#ARGS[@]}-1]} 

Điều này cũng có tác dụng đối với bash 4.x.

+0

Tôi nhận được: gsMerge infile1.pdf infile2.pdf all.pdf /usr/bin/gsMerge: dòng 4: ARGS: chỉ số mảng xấu **** Không thể mở thiết bị ban đầu, thoát. –

+0

@Marius: Có thể bạn đang sử dụng phiên bản cũ của 'bash'. Tôi đã cập nhật câu trả lời để đề cập đến trường hợp đó. – Idelic

+0

Cảm ơn, Idelic, rất tốt. –

7

Để truy cập vào đối số cuối cùng, ngoài câu trả lời Idelic của trên, bạn cũng có thể làm:

echo "${@: $#}" 

này đọc tất cả các đối số và in chúng bắt đầu từ người cuối cùng. Bằng cách này, bạn cũng có thể truy cập N đối số cuối cùng, ví dụ cho ba đối số cuối cùng:

echo "${@: $#-2}" 

$ ./script "what does" "this script" "do" "?" 
this script do ? 
+0

Ồ, điều này thật tuyệt vời. Điều này được xác định ở đâu trong sách hướng dẫn? Và có một phiên bản phạm vi này? –

+0

Xem câu trả lời này: [link] (https://stackoverflow.com/questions/1335815/how-to-slice-an-array-in-bash) về mảng nối, câu trả lời ở trên chỉ đơn giản là sử dụng để cắt mảng đối số đầu vào. –

Các vấn đề liên quan