【Shell编程】Shell脚本中各类参数传递以及获取

Linux Shell 参数传递与获取完全指南

一、基础参数传递方式

1. 位置参数(Positional Parameters)

#!/bin/bash
调用方式:./script.sh param1 "param 2" param3

echo "脚本名称: $0"        # 脚本路径
echo "第一个参数: $1"      # param1
echo "第二个参数: $2"      # param 2 (保留空格)
echo "参数总数: $#"        # 3
echo "所有参数: $*"        # "param1 param 2 param3"(合并为单字符串)
echo "所有参数: $@"        # "param1" "param 2" "param3"(保持独立)

2. 特殊参数变量

变量描述示例
$#参数个数if [ $# -eq 0 ]; then...
$*所有参数合并为单字符串for arg in "$*"; do...
$@所有参数独立保留for arg in "$@"; do...
$?上条命令退出状态if [ $? -ne 0 ]; then...
$$当前进程PIDecho "PID: $$"
$!最后一个后台进程PIDfirefox & echo "Firefox PID: $!"

二、参数获取高级技巧

1. 参数遍历方法

方法1:直接遍历$@
for param in "$@"; do
  echo "参数: $param"
done

方法2:使用shift逐项处理
while [ "$1" != "" ]; do
  case $1 in
    -f|--file) shift; file=$1 ;;
    -v|--verbose) verbose=1 ;;
    *) echo "未知参数: $1"; exit 1 ;;
  esac
  shift  # 移除已处理的参数
done

2. 默认值设置

如果未传参则使用默认值
username=${1:-"guest"}
port=${2:-8080}

冒号语法(变量为空时也触发)
logfile=${LOG_FILE:?"必须设置LOG_FILE环境变量"}

三、命令行选项解析

1. getopts(标准Unix方式)

#!/bin/bash
while getopts ":a:b:c" opt; do
  case $opt in
    a) arg_a="$OPTARG" ;;
    b) arg_b="$OPTARG" ;;
    c) flag_c=1 ;;
    \?) echo "无效选项: -$OPTARG" >&2 ;;
    :) echo "选项 -$OPTARG 需要参数" >&2 ;;
  esac
done
shift $((OPTIND-1))  # 移除已解析选项

调用示例:./script.sh -a value -b "test" -c file.txt

2. getopt(增强版,支持长选项)

#!/bin/bash
TEMP=$(getopt -o ab:c:: --long alpha,beta:,gamma:: -n '示例' -- "$@")
eval set -- "$TEMP"

while true; do
  case "$1" in
    -a|--alpha) alpha=1; shift ;;
    -b|--beta) beta="$2"; shift 2 ;;
    -c|--gamma) 
      case "$2" in
        "") gamma="default"; shift 2 ;;
        *) gamma="$2"; shift 2 ;;
      esac ;;
    --) shift; break ;;
    *) echo "内部错误"; exit 1 ;;
  esac
done

调用示例:./script.sh --alpha --beta "value" --gamma=opt

四、参数验证与安全

1. 必填参数检查

required_params=("host" "port")
missing_params=()

for param in "${required_params[@]}"; do
  if [ -z "${!param}" ]; then  # 间接引用变量
    missing_params+=("$param")
  fi
done

if [ ${#missing_params[@]} -gt 0 ]; then
  echo "缺少必要参数: ${missing_params[*]}"
  exit 1
fi

2. 类型校验

数字校验
if ! [[ "$port" =~ ^[0-9]+$ ]]; then
  echo "端口必须是数字"
  exit 1
fi

文件存在检查
if ! [ -f "$input_file" ]; then
  echo "输入文件不存在: $input_file"
  exit 1
fi

IP地址校验
if ! [[ "$ip" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
  echo "无效IP地址"
  exit 1
fi

五、实用模式示例

1. 子命令模式(类似git)

case "$1" in
  start)
    shift  # 移除子命令参数
    echo "启动服务,参数: $@" ;;
  stop)
    shift
    echo "停止服务,参数: $@" ;;
  *)
    echo "用法: $0 {start|stop} [options]"
    exit 1 ;;
esac

调用示例:./service.sh start --port 8080

2. 参数注入防护

危险!可能执行任意命令
eval "$1"

安全做法:白名单验证
allowed_commands=("start" "stop" "restart")
if [[ " ${allowed_commands[*]} " =~ " $1 " ]]; then
  case "$1" in
    start) ./start_service.sh ;;
    stop) ./stop_service.sh ;;
  esac
else
  echo "无效命令"
fi

六、性能优化技巧

1. 参数缓存处理

缓存解析结果
parse_args() {
  local args=("$@")
  ARG_CACHE=""
  for arg in "${args[@]}"; do
    ARG_CACHE+="$(printf '%q' "$arg") "
  done
}

后续使用缓存
eval "set -- $ARG_CACHE"

2. 批量参数处理

使用关联数组存储参数
declare -A params
while IFS='=' read -r key value; do
  params["$key"]="$value"
done < <(printf '%s\n' "$@")

访问示例
echo "用户名: ${params["user"]}"
echo "端口: ${params["port"]}"

七、跨脚本参数传递

1. 导出到环境变量

主脚本
export DB_HOST="db.example.com"
export DB_PORT=3306
./subscript.sh

subscript.sh
echo "连接数据库: ${DB_HOST}:${DB_PORT}"

2. 通过文件传递

生成参数文件
cat > params.conf <<EOF
input_file=/data/sample.txt
output_dir=/var/reports
max_records=1000
EOF

读取参数文件
source params.conf
echo "处理文件: $input_file"

最佳实践总结

  1. 命名规范:使用有意义的参数名(如--input-file优于-i
  2. 错误处理:对非法参数立即退出并显示帮助
  3. 安全防护:始终验证和清理输入参数
  4. 文档注释:在脚本头部添加参数说明

示例帮助文档:

usage() {
  cat <<EOF
用法: ${0##*/} [选项] 文件...

选项:
  -h, --help      显示此帮助信息
  -v, --verbose   显示详细输出
  -o 文件         指定输出文件
  --version       显示版本信息

示例:
  ${0##*/} -o result.txt input*.log
EOF
  exit ${1:-0}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

问道飞鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值