如何向Bash函数传递两个可变参数列表实现命令封装?
Bash/Zsh 双参数列表findgrep函数实现方案
核心问题
最初的find $1 -exec grep -H $2 \{\} \;写法只能接收两个单值参数,无法分别给find和grep传递多组可变参数,把两组参数分别用引号包裹成字符串传入的方案,需要额外处理字符串拆分,极易出现空格、通配符解析错误。
通用基础实现(bash/zsh双兼容)
采用Unix工具通用的--作为两组参数的分隔符,前半部分所有参数传给find,后半部分所有参数传给grep,全程用数组存储参数避免解析错误:
findgrep() { local find_args=() local grep_args=() local split=0 for arg in "$@"; do if [[ $arg == "--" ]]; then split=1 continue fi (( split == 0 )) && find_args+=("$arg") || grep_args+=("$arg") done if [[ ${#find_args[@]} -eq 0 || ${#grep_args[@]} -eq 0 ]]; then echo "用法: findgrep [find所有参数] -- [grep所有参数]" echo "示例: findgrep src app -name '*.hs' -- -Hn 'foo'" return 1 fi find "${find_args[@]}" -exec grep "${grep_args[@]}" {} \; }
调用示例
不需要给参数额外套引号,直接按正常命令写法传参即可:
# 等价于你原始的find命令 findgrep src app -name "*.hs" -- -H "foo" # 给grep加行号、忽略大小写参数无需修改函数 findgrep src -name "*.py" -- -Hni "test_func"
偏应用效果实现
轻量方案:手动封装专用函数
如果需要固定一部分find参数生成专用命令,直接封装一层即可,没有额外复杂度:
# 绑定find参数:搜索src/app目录下所有.hs文件 hsgrep() { findgrep src app -name "*.hs" -- "$@" } # 后续直接调用,只传grep参数即可 hsgrep -H "foo" hsgrep -n "bar"
通用动态偏应用方案
如果需要动态绑定参数、不提前写死专用函数,可以给函数加判断:当只传入find侧参数、没有传--和grep参数时,动态生成绑定了已有参数的新函数:
findgrep() { local find_args=() local grep_args=() local split=0 for arg in "$@"; do if [[ $arg == "--" ]]; then split=1 continue fi (( split == 0 )) && find_args+=("$arg") || grep_args+=("$arg") done # 未传入分隔符时,返回绑定了当前find参数的新函数 if (( split == 0 )); then local func_name="_fg_$(date +%s%N)" local quoted_args=() for a in "${find_args[@]}"; do quoted_args+=("$(printf '%q' "$a")") done eval " $func_name() { findgrep ${quoted_args[*]} -- \"\$@\" } " echo "$func_name" return 0 fi if [[ ${#find_args[@]} -eq 0 || ${#grep_args[@]} -eq 0 ]]; then echo "用法: findgrep [find参数] -- [grep参数]" echo "偏应用: mygrep=\$(findgrep src app -name '*.hs') && \$mygrep 'foo'" return 1 fi find "${find_args[@]}" -exec grep "${grep_args[@]}" {} \; }
动态偏应用调用示例
# 绑定find参数生成专用grep函数 hsgrep=$(findgrep src app -name "*.hs") # 直接调用生成的函数即可 $hsgrep "foo" $hsgrep -n "bar"
方案优势
- 全程用数组传递参数,不会出现空格、特殊字符、通配符被错误解析的问题
- 采用POSIX标准的
--作为参数分隔符,符合常规命令使用习惯,学习成本为0 - 同时兼容bash和zsh,不需要做分支适配
- 偏应用实现灵活度高,既可以手动封装固定专用命令,也可以动态生成绑定参数的临时函数
内容的提问来源于stack exchange,提问作者zaabson
相关产品推荐
相关产品推荐

