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

Bash参数拆分需求:按空格分割且保留引号的可移植实现

问题描述

给定Bash参数:

foo='ab   "cd" "e f"  x="1 2" '

需要将其转换为等价于以下定义的数组:

foo_transformed=( ab '"cd"' '"e f"' 'x="1 2"' )

要求实现方案满足:

  • 可移植性:仅使用Bash v3+内置命令或Linux、Unix、Cygwin默认自带程序
  • 安全性与准确性:适配任意空白字符(分隔符或双引号内的空白),保留原字符串中的双引号
  • 已知输入限制:不含单引号'或反斜杠\

此前尝试的两种方法均无法满足需求:

  1. 直接赋值:

    foo_transformed=( $foo )
    

    无法识别双引号作为分组标记,输出结果会将引号内的空白也当作分隔符:

    - ab
    - "cd"
    - "e
    - f"
    - x="1
    - 2"
    
  2. 使用eval:

    eval foo_transformed=( $foo )
    

    会解析并丢弃双引号,导致元素内容丢失引号:

    - ab
    - cd
    - e f
    - x=1 2
    
解决方案

通用方案(基于GNU awk)

使用awk的FPAT特性(GNU awk 3.1.5+支持,多数系统默认自带)准确定义字段规则,结合Bash循环读取构建数组:

foo_transformed=()
while IFS= read -r elem; do
    foo_transformed+=("$elem")
done < <(awk 'BEGIN { FPAT = "([^[:space:]]+)|(\"[^\"]+\")" } { for (i=1; i<=NF; i++) print $i }' <<<"$foo")

验证结果

执行遍历命令:

for k in "${foo_transformed[@]}"; do echo "- $k"; done

输出符合预期:

- ab
- "cd"
- "e f"
- x="1 2"

原理说明

  • FPAT = "([^[:space:]]+)|(\"[^\"]+\")":定义两个匹配规则,要么是不含空白的连续字符,要么是被双引号包裹、内部不含双引号的字符串,精准区分分隔空白与引号内的空白。
  • awk遍历匹配到的字段逐行输出,Bash循环读取每一行作为数组元素,完整保留原内容(包括双引号)。

兼容BSD awk方案(如macOS默认环境)

若系统默认使用BSD awk(不支持FPAT),可改用自定义分割逻辑实现:

foo_transformed=()
while IFS= read -r elem; do
    foo_transformed+=("$elem")
done < <(awk '{
    str = $0
    while (length(str) > 0) {
        if (substr(str, 1, 1) == "\"") {
            end = index(substr(str, 2), "\"") + 1
            elem = substr(str, 1, end)
            str = substr(str, end + 1)
        } else {
            end = match(str, /[[:space:]]/)
            if (end == 0) {
                elem = str
                str = ""
            } else {
                elem = substr(str, 1, end - 1)
                str = substr(str, end + 1)
            }
        }
        gsub(/^[[:space:]]+|[[:space:]]+$/, "", elem)
        if (length(elem) > 0) print elem
    }
}' <<<"$foo")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 00:07:23