用Bash解析MySQL语句转JSON时,如何区分字符串内逗号与分隔逗号?
纯Bash实现带逗号字符串的SQL值拆分方案
问题根源
你当前脚本的拆分逻辑存在明确的语义识别缺陷:所有逗号都被当作拆分边界,没有区分SQL语法中两类逗号的不同作用:
- 分隔字段的逗号:位于单引号包裹范围外,是合法的拆分点
- 字符串内容里的逗号:被单引号包裹,属于值的一部分,不能作为拆分标记
这种情况下不管怎么调整参数替换的写法、或者写全局匹配的正则,都没法正确识别逗号位置,因为Bash的内置参数替换、正则引擎都不支持追踪单引号开闭的状态,碰到单引号内的逗号必然会错误拆分。
可行实现思路
纯Bash环境下最可靠的方案是逐字符遍历+状态标记,不需要依赖外部编程语言:
- 维护一个状态位标记当前遍历的位置是否在单引号包裹的字符串内部
- 遇到单引号时切换状态,同时兼容SQL规范里的转义规则:连续两个单引号
''代表字符串内部的单引号,不属于字符串包裹边界,不切换状态 - 只有当状态位显示当前在单引号外部、且碰到逗号时,才认定这个位置是合法的拆分边界,把之前收集的字符作为一个独立值输出
核心拆分函数实现
# 拆分SQL格式的逗号分隔值,自动忽略单引号内的逗号 split_sql_kv() { local raw_input="$1" local current_chunk="" local in_single_quote=0 # 逐字符遍历输入内容 for ((idx=0; idx<${#raw_input}; idx++)); do current_char="${raw_input:idx:1}" # 处理SQL转义的单引号 if [[ $current_char == "'" ]]; then # 连续两个单引号是转义字符,直接保留,不切换状态 if [[ "${raw_input:idx+1:1}" == "'" ]]; then current_chunk+="''" ((idx++)) continue fi # 切换单引号包裹状态 in_single_quote=$((1 - in_single_quote)) fi # 遇到单引号外的逗号,输出当前收集的值 if [[ $current_char == "," && $in_single_quote -eq 0 ]]; then # 去掉值前后多余的空格 current_chunk="${current_chunk#" "}" current_chunk="${current_chunk%" "}" echo "$current_chunk" current_chunk="" continue fi current_chunk+="$current_char" done # 输出最后一个剩余的值 current_chunk="${current_chunk#" "}" current_chunk="${current_chunk%" "}" echo "$current_chunk" }
效果验证
拿你提供的测试输入做验证:
# 测试值:100, 'A100', 'A,100' test_input="100, 'A100', 'A,100'" split_sql_kv "$test_input"
输出结果和预期完全一致:
100 'A100' 'A,100'
脚本适配方法
把你原来脚本里通过names%%,*、values%%,*逐次切分逗号的循环逻辑,替换成上述split_sql_kv函数即可。字段名部分本身不存在单引号包裹的带逗号内容,原有逻辑可以保留不调整。
内容的提问来源于stack exchange,提问作者ogmskd lksdrq
相关产品推荐
相关产品推荐

