如何将串联Bash命令的字符串拆分为命令与分隔符数组?
拆分Bash命令字符串为命令与分隔符数组的解决方案
针对Bash中无法用IFS拆分多字符命令分隔符的问题,这里提供两种可行的原生工具方案:
方案一:Bash正则循环提取
利用Bash的正则匹配功能,循环提取命令和分隔符,无需外部工具:
x="cmd1 2&>1 && cmd2 || cmd3 ; cmd4 | cmd5" y=() # 循环匹配命令、分隔符及剩余字符串 while [[ $x =~ ^(.*?)([[:space:]]*(&&|\|\||;|\|)[[:space:]]*)(.*)$ ]]; do # 添加提取到的命令 y+=("${BASH_REMATCH[1]}") # 提取分隔符并去除前后空格 sep=$(echo "${BASH_REMATCH[2]}" | xargs) y+=("$sep") # 更新字符串为剩余部分 x="${BASH_REMATCH[3]}" done # 添加最后一段命令 [[ -n $x ]] && y+=("$x") # 测试输出(可选) for i in "${!y[@]}"; do echo "y[$i] = '${y[$i]}'" done
运行后数组y的内容符合需求:
y[0] = 'cmd1 2&>1'y[1] = '&&'y[2] = 'cmd2'y[3] = '||'- ...以此类推
方案二:sed替换+IFS拆分
通过sed将多字符分隔符替换为单一特殊标记,再用IFS拆分:
x="cmd1 2&>1 && cmd2 || cmd3 ; cmd4 | cmd5" # 先替换长分隔符(&&、||),再替换短分隔符(;、|),避免误拆分 processed=$(echo "$x" | sed -E 's/[[:space:]]*&&[[:space:]]*/\x01&&\x01/g; s/[[:space:]]*\|\|[[:space:]]*/\x01\|\|\x01/g; s/[[:space:]]*;[[:space:]]*/\x01;\x01/g; s/[[:space:]]*\|[[:space:]]*/\x01\|\x01/g') # 用空字符作为分隔符拆分到数组 readarray -d $'\x01' -t y <<< "$processed" # 清除数组中的空元素(处理首尾可能的空值) y=("${y[@]//^$}") # 测试输出(可选) for i in "${!y[@]}"; do echo "y[$i] = '${y[$i]}'" done
注意事项
两种方案都适用于常见场景,但如果命令中包含带分隔符的字符串(比如echo "a && b"),正则会误拆分这类字符串内部的符号。如果需要处理这种复杂情况,得依赖Bash的语法解析器,比如通过bash -n配合自定义脚本分析,但实现成本会高很多。
内容的提问来源于stack exchange,提问作者Jee Force
相关产品推荐
相关产品推荐

