從 shell 腳本呼叫命令,傳遞大多數參數,允許帶空格的參數
我有一個批量執行 SAS 程式碼
run_sas.sh
的命令的包裝器。sas
典型的呼叫如下所示./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder/my_program.log
run_sas.sh
將所有參數傳遞給sas
with./sas $*
。sas
然後執行/my_code/my_program.sas
並將日誌寫入/my_log_folder/my_program.log
.- 然後
run_sas.sh
分析它被呼叫的參數- 並將日誌複製到
/admin/.hidden_log_folder/my_program_<today's date>.log
我想做兩個改變:
啟用多字參數
有些客戶絕對希望我在文件夾和文件名中使用空格並要求我執行
/their code/their program.sas
,所以如果我執行./run_sas.sh -sysin "/their code/their program.sas" -log "/their log folder"
/their code/their program.sas
並且/their log folder
應該將單個參數傳遞給sas
刪除特定參數
有時我需要執行
./sas_utf8
而不是./sas
我懶得維護第二個腳本,所以我想允許一個額外的參數,這樣./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder -encoding utf8
會打電話
./sas_utf8 -sysin /my_code/my_program.sas -log /my_log_folder
代替
./sas -sysin /my_code/my_program.sas -log /my_log_folder
我該怎麼做,最好是在
ksh
?
首先,使用
"$@"
代替$*
(或$@
)來保持參數不變。它將每個參數擴展為一個單獨的單詞,就好像您使用"$1" "$2"...
了注意,使用$*
, glob 字元也是一個問題。要查找 utf8 選項,您可以遍歷命令行參數,然後將要保留的參數複製到另一個數組,並在看到
-encoding
and時設置一個標誌utf8
。然後只需檢查標誌變數以確定要執行的程序,並傳遞
"${sasArgs[@]}"
給命令。所以:
executable="./sas_u8" # The default # Inspect the arguments, # Remember where the log is written # Change the executable if the encoding is specified # Copy all arguments except the encoding to the 'sasArgs' array while [[ "$#" -gt 0 ]]; do case "$1" in -encoding) # change the executable, but do not append to sasArgs if [[ "$2" = "utf8" ]]; then executable="./sas_u8" shift 2 continue else echo "The only alternative encoding already supported is utf8" >&2 exit 1 fi ;; -log) # remember the next argument to copy the log from logPath="$2" ;; esac sasArgs+=("$1") shift done # To debug: print the args, enclosed in "<>" to discover multi word arguments printf "Command and args: " printf "<%s> " "$cmd" "${sasArgs[@]}" printf "\n" # exit # when debugging # Actually run it "$executable" "${sasArgs[@]}" # Copy the log using $logPath # ...
最後一次
printf
呼叫列印它將執行的參數,<>
每個參數都有,因此您可以檢查帶有空格的參數是否保持不變。(您可以執行echo "${sasArgs[@]}"
,但它無法從單個參數中分辨出兩個參數foo
和。)bar``foo bar
for
如果我們正在尋找單個參數,而不是兩個參數對,則可以使用循環使第一部分變得更簡單:for arg in "$@" do case "$arg" in -encoding-utf8) # change the executable, but do not append to the array executable="./sas_u8" continue ;; esac sasArgs+=("$arg") done
這也可以轉換為普通的 POSIX sh。循環複製它給出的
for
列表,因此複製的參數可以儲存回位置參數(附加set -- "$@" "$arg"
)而不是使用數組。此外,如果知道編碼參數在開始時,整個交易可以變得更簡單。
$1
然後檢查(and )就足夠了$2
,它們可以用 . 刪除shift
。(我用 Bash 和我在 Debian 上的 ksh93 版本測試了上面的腳本。我對 ksh 不太熟悉,所以我可能遺漏了一些東西。但是 Bash 的數組是從 ksh 複製的,所以我希望它應該可以正常工作同時。)