You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在POSIX Shell脚本中用函数封装含shift的重复case逻辑?

POSIX Shell中封装位置参数处理函数的安全性问题

问题背景

POSIX兼容Shell脚本仅支持位置参数数组,不支持其他数组。主脚本中多个case分支需执行包含位置参数shift操作的重复代码(实际代码超10行),为减少代码重复,需将该逻辑封装为函数。尝试了一种通过函数处理参数后用eval重置位置参数的方案,已修复换行截断问题,但担忧仅转义单引号的方式是否足够安全,参考getopt的实现发现,除tcsh外它也仅转义单引号。

原脚本示例

#!/bin/sh
# /tmp/test.sh

case "$1" in
( *one*   ) echo 1 ; shift ; echo 'more' ;;
( *two*   ) echo 2 ; shift ; echo 'more' ;;
( *three* ) echo 3 ; shift ; echo 'more' ;;
( other ) echo 'other' ;;
( * ) :
esac

printf '[%s]\n' "$@"

原脚本测试输出

$ /tmp/test.sh 'arg one'  '3   spaces' "with 'quotes'"
1
more
[3   spaces]
[with 'quotes']

尝试的解决方案脚本

#!/bin/sh
# /tmp/test.sh

newline=$(printf '\n ')
newline=${newline% }

func() {
    # Perform something based on arg $1.
    # But do not echo here. echo here will mess up with the return value.
    # Actual code do not echo here.
    # echo "$1"
    shift

    shift

    # Escape dangerous characters and preserve spaces
    modified_args=""
    for arg in "$@"; do
        trailing_newlines=${arg##*[!${newline}]}
        modified_args="${modified_args} '$(printf "%s" "$arg" | sed "s/'/'\\\\''/g")${trailing_newlines}'"
    done
    printf '%s' "$modified_args"
}

 case "$1" in
    ( *one*   ) args=$(func 1 "$@") ; eval set -- "$args" ;;
    ( *two*   ) args=$(func 2 "$@") ; eval set -- "$args" ;;
    ( *three* ) args=$(func 3 "$@") ; eval set -- "$args" ;;
    ( other ) echo 'other' ;;
    ( * ) :
    esac


printf '[%s]\n' "$@"              

解决方案测试输出

$ newline=$(printf '\n ')
$ newline=${newline% }
$ /tmp/test.sh 'arg one'  '3   spaces' '' "with 'quotes'" 'double "quote"' "$newline line two $newline line three $newline$newline"
[3   spaces]
[]
[with 'quotes']
[double "quote"]
[
 line two 
 line three 

]

安全性疑问

经@KamilCuk提示修改后已修复换行截断问题,但仍担忧仅转义单引号的方式是否足够安全。参考getopt的实现发现,除tcsh外它也仅转义单引号。


内容的提问来源于stack exchange,提问作者midnite

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 07:40:22