2012-04-24 96 views
22

我想通過shell腳本定義一個調用gs(ghostscript)的簡單縮寫。第一個參數給出了所有應該合併的文件,最後一個給出了輸出文件的名稱。顯然,下面不工作(這只是用於顯示的目標):如何用可變數量的參數定義一個shell腳本?

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

如何才能做到這一點?

通常會通過myscript infile1.pdf infile2.pdf ... outfile.pdfmyscript *.pdf outfile.pdf調用此腳本。

回答

34

bash變量[email protected]$*擴展到命令行參數列表中。一般來說,你會想要使用"[email protected]"(即,用雙引號包圍的[email protected])。如果有人將你的腳本傳遞給包含空格的參數,這會做正確的事情。

所以,如果你在你的腳本有這樣的:

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

你叫你的腳本是這樣的:

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

這將擴展爲:

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

閱讀"Special Parameters"有關更多信息,請參見bash手冊頁。

+0

謝謝。輸出文件名可能是* last *(不是第一個)參數嗎? – 2012-04-24 23:32:19

+0

Marius Hofert:你不可能輕易地將最後一個元素轉移出去,所以這有點棘手。像這樣:'outputfile = $ {@:-1}; ARGS =( 「$ {@:1:$(($ {#@} - 1))}」)'。你應該接受這個騙局的答案。 – jordanm 2012-04-25 01:43:43

+0

你*可以*,但它有點難看。 Idelic在他的回答中有一個例子。你最終會在代碼中引入更多的東西。 – larsks 2012-04-25 02:50:06

18

要通過輸出文件作爲最後一個參數,使用數組:

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

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

4版之前,bash沒有允許在陣列負下標(和產生由馬呂斯評價報告的錯誤) ,所以如果你使用的是3.x,你需要使用更多的醜陋手段。

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

這也適用於bash 4.x。

+0

我獲得: gsMerge infile1.pdf infile2.pdf all.pdf /usr/bin/gsMerge:第4行:ARGS:壞數組下標 ****無法打開初始設備,退出。 – 2012-04-25 05:59:53

+0

@Marius:您可能使用的是舊版本的'bash'。我更新了涵蓋該案例的答案。 – Idelic 2012-04-25 14:48:43

+0

謝謝,Idelic,非常好。 – 2012-04-25 15:08:28

7

要訪問的最後一個參數,除了Idelic的回答上面,你也可以這樣做:

echo "${@: $#}" 

這讀取所有的參數和打印他們從最後一個開始。這樣,您還可以訪問N個最後一個參數,例如最後三個參數:

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

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

哇,這太棒了。這在手冊中定義在哪裏?有沒有這個範圍版本? – 2017-05-07 01:40:00

+0

看到這個答案:[鏈接](https://stackoverflow.com/questions/1335815/how-to-slice-an-array-in-bash)關於拼接數組,上面的答案是簡單地使用它來切片數組的輸入參數。 – 2017-05-08 11:29:54