跳到正文

参数与 flag ​

程序收到的永远是一个字符串数组,选项和路径怎么解释,全靠约定。

argv ​

bash
ls -l folder/
# 程序收到 ["ls", "-l", "folder/"]
概念说明
argv[0]程序名
argv[1..]参数列表
类型全是字符串,没有数字或布尔
解释权在程序,不在 Shell

选项约定 ​

规则例子
短选项-a
长选项--all
两者等价ls -a = ls --all
短选项合并-la = -l -a
顺序无关-la = -al
可变文件参数rm a b c
通用选项--help、--version、--verbose
bash
touch -- -myfile
rm -- -myfile

-- 之后不再解析选项,所有减号开头的字符串都当位置参数。

脚本里的位置参数 ​

变量含义
$0脚本名
$1…$9前九个参数
$#参数个数
$@全部参数
"$@"每个参数独立

不加引号的 $@ 会重新切词,遍历参数几乎总是写 "$@"。

手动解析 ​

bash
while [[ $# -gt 0 ]]; do
  case "$1" in
    -v|--verbose) verbose=1; shift ;;
    --) shift; break ;;
    *) files+=("$1"); shift ;;
  esac
done

复杂参数不要手写:Python 用 argparse,Go 用 flag,Rust 用 clap。

glob 在启动前展开 ​

rm *.py 里,rm 收到的是展开后的文件名,不是 *.py。所以程序无法区分参数是手写的还是 Shell 展开的,带空格的参数必须用引号一路带到程序。

环境变量是另一条通道:不占 argv,子进程默认继承,适合配置而不是数据。