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

如何在Bash/Posix中展开存储于另一变量中的特殊参数?

Bash特殊参数引号差异测试方案

需求说明

想要编写脚本测试Bash中$*、"$*"、$@、"$@"这几个特殊参数带引号和不带引号的行为差异,要求在循环中同时获取参数的名称(比如$*)和它对应的实际值(比如传入arg1 arg2时,$*对应拆分后的arg1、arg2,"$*"对应合并后的arg1 arg2)。

之前的尝试中,用单引号给args赋值只能拿到参数名称,双引号赋值只能拿到值,间接展开${!a}也无法生效,需要找到可行的实现方式。

Bash 实现方案

利用数组存储要测试的参数名称,通过case分支区分不同参数的行为,避免使用风险较高的eval:

#!/bin/bash

# 定义待测试的特殊参数名称列表
test_params=(
    '$*'
    '"$*"'
    '$@'
    '"$@"'
)

# 遍历每个参数名称
for param in "${test_params[@]}"; do
    echo "$param"
    # 根据参数名称执行对应逻辑
    case "$param" in
        '"$*"')
            echo "$*"
            ;;
        '$*')
            for arg in $*; do
                echo "$arg"
            done
            ;;
        '"$@"')
            for arg in "$@"; do
                echo "$arg"
            done
            ;;
        '$@')
            for arg in $@; do
                echo "$arg"
            done
            ;;
    esac
    echo "---"
done

执行示例(传入./script arg1 arg2):

$*
arg1
arg2
---
"$*"
arg1 arg2
---
$@
arg1
arg2
---
"$@"
arg1
arg2
---

POSIX 兼容实现方案

由于POSIX Shell没有数组,需要用字符串保存测试参数列表,同时提前保存原始传入参数,通过eval恢复原始参数(注意:eval存在安全风险,仅在可控场景下使用):

#!/bin/sh

# 保存原始传入的参数,用于后续恢复
original_args_count=$#
original_args=""
for i in $(seq 1 "$original_args_count"); do
    original_args="$original_args \"\$$i\""
done

# 定义待测试的参数名称列表
test_params='$* "$*" $@ "$@"'

# 遍历每个参数名称
for param in $test_params; do
    echo "$param"
    case "$param" in
        '"$*"')
            # 模拟"$*"的行为:用默认IFS连接所有参数
            IFS_save=$IFS
            IFS=' '
            echo "$*"
            IFS=$IFS_save
            ;;
        '$*')
            # 模拟$*的行为:按IFS拆分参数
            IFS_save=$IFS
            IFS=' '
            for arg in $*; do
                echo "$arg"
            done
            IFS=$IFS_save
            ;;
        '"$@"')
            # 恢复原始参数,模拟"$@"的行为:逐个输出独立参数
            eval "set -- $original_args"
            for arg do
                echo "$arg"
            done
            ;;
        '$@')
            # 恢复原始参数,模拟$@的行为:按IFS拆分参数
            eval "set -- $original_args"
            IFS_save=$IFS
            IFS=' '
            for arg in $@; do
                echo "$arg"
            done
            IFS=$IFS_save
            ;;
    esac
    echo "---"
done

注意事项

根据BashFAQ的建议,强烈不建议在变量中存储字符串以外的语法内容(比如直接存储"$*"作为变量值试图间接展开),这类操作会涉及Shell的语法解析问题,容易引发意外行为或安全风险。优先通过明确的分支逻辑区分不同参数的行为,避免依赖eval这类危险操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 20:51:19