Ksh

從 shell 腳本呼叫命令,傳遞大多數參數,允許帶空格的參數

  • June 3, 2022

我有一個批量執行 SAS 程式碼run_sas.sh的命令的包裝器。sas典型的呼叫如下所示

./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder/my_program.log
  • run_sas.sh將所有參數傳遞給saswith ./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 選項,您可以遍歷命令行參數,然後將要保留的參數複製到另一個數組,並在看到-encodingand時設置一個標誌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 複製的,所以我希望它應該可以正常工作同時。)

引用自:https://unix.stackexchange.com/questions/704748