我在命令run_sas.sh周围有一个包装器sas,它可以批量运行SAS代码。一个典型的电话看起来像这样
./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder/my_program.logrun_sas.sh将所有参数与./sas $*一起传递给sas。sas运行/my_code/my_program.sas并将日志写入/my_log_folder/my_program.log。run_sas.sh分析用它调用的参数/admin/.hidden_log_folder/my_program_.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?
发布于 2022-06-02 20:53:12
首先,使用"$@"而不是$* (或$@)来保持参数不变。它将每个参数扩展为一个单独的单词,就好像您使用了"$1" "$2"...注意到,对于$*,glob字符也是一个问题。
要查找utf8 8-选项,可以遍历命令行参数,并将要保留的参数复制到另一个数组,如果看到-encoding和utf8,则设置一个标志。
然后,只需检查标志变量以确定要运行哪个程序,并将"${sasArgs[@]}"传递给命令。
所以:
executable="./sas" # The default, for latin encoding
# 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 (和$2)就足够了,并且可以用shift删除它们。
(我用Bash和Debian上的ksh93版本测试了上面的脚本。我对ksh不太熟悉,所以我可能漏掉了什么。但是Bash的数组是从ksh复制的,所以我希望它在这两个方面都能正常工作。)
https://unix.stackexchange.com/questions/704748
复制相似问题