首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从shell脚本调用命令,传递大部分参数,允许带空格的参数

从shell脚本调用命令,传递大部分参数,允许带空格的参数
EN

Unix & Linux用户
提问于 2022-06-02 16:00:11
回答 1查看 1.3K关注 0票数 1

我在命令run_sas.sh周围有一个包装器sas,它可以批量运行SAS代码。一个典型的电话看起来像这样

代码语言:javascript
复制
./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder/my_program.log
  • run_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,所以如果我运行

代码语言:javascript
复制
./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,而且我太懒,无法维护第二个脚本,所以我希望允许一个额外的参数,以便

代码语言:javascript
复制
./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder -encoding utf8

会打电话

代码语言:javascript
复制
./sas_utf8 -sysin /my_code/my_program.sas -log /my_log_folder

而不是

代码语言:javascript
复制
./sas -sysin /my_code/my_program.sas -log /my_log_folder

我怎样才能做到这一点,最好是在ksh

EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2022-06-02 20:53:12

首先,使用"$@"而不是$* (或$@)来保持参数不变。它将每个参数扩展为一个单独的单词,就好像您使用了"$1" "$2"...注意到,对于$*,glob字符也是一个问题。

要查找utf8 8-选项,可以遍历命令行参数,并将要保留的参数复制到另一个数组,如果看到-encodingutf8,则设置一个标志。

然后,只需检查标志变量以确定要运行哪个程序,并将"${sasArgs[@]}"传递给命令。

所以:

代码语言:javascript
复制
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中分辨出两个参数foobar。)

如果我们寻找的是单个参数,而不是两个参数对,那么使用for循环可以使第一部分变得简单一些:

代码语言:javascript
复制
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复制的,所以我希望它在这两个方面都能正常工作。)

票数 3
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/704748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档