You need to enable JavaScript to run this app. Shell脚本对比存储多行SQL的数组以输出A.sql独有内容的问题排查
优惠活动
大模型
产品
解决方案
定价
更多

Shell脚本对比存储多行SQL的数组以输出A.sql独有内容的问题排查

原脚本存在的核心问题
  • 读取B.sql的语法错误:拆分B.sql的循环中,read -rd ';'second_sql 缺少分隔符参数与变量名之间的空格,shell 会把 ;second_sql 整体作为 -d 的自定义分隔符,完全无法按分号拆分B.sql内容,导致存储B.sql的数组内容完全失真。这也是你运行脚本时只输出第一条SQL的核心原因。
  • read -d 模式的内容丢失风险:read 只有碰到指定分隔符时才会返回成功退出码,如果文件最后一段SQL结尾没有分号,或是读到文件EOF仍未匹配到分隔符,read 会返回非零值,对应SQL块会被直接丢弃,无法存入数组。
  • 变量引用不规范:匹配判断语句[[ $p == $q ]]未给变量加双引号,当SQL内容包含通配符(比如SQL里的*)、特殊字符时,会被shell解析成通配匹配规则,导致判断结果错误。
  • 对比逻辑完全错乱:
    • 匹配成功时的提示文本写错,将"SQL存在于B数组"的判断逻辑误写为"属于first_array"
    • 没有基于flag的分支判断,不管SQL是否在B数组中存在,都会执行后续的"不存在"输出,还夹杂了多余的调试输出(echo $flag)
    • 缺少核心分支:只有当flag为false(即B数组中找不到匹配项)时,才需要输出A中独有的内容,原脚本完全没有实现这个判断逻辑。
  • SQL内容未做规范化处理:因为单条SQL跨多行存储,拆分后的内容会自带前后换行、缩进、行内连续空白,哪怕两条SQL语义完全一致,只要空白、换行的位置不同就会被判定为不匹配,产生大量误判。
脚本修改方案

针对上述问题做对应调整:

  1. 修正所有语法空格问题,给read参数、变量引用加上正确的空格与双引号
  2. 给每个拆分出的SQL块做规范化处理:用tr把跨行换行、连续缩进/空格统一替换为单个空格,去掉内容前后的多余空白,消除格式差异导致的匹配失败
  3. 专门处理文件末尾无分号的场景:即使read因为读到EOF返回非零,只要存在有效未存储的SQL块,就将其存入对应数组
  4. 理顺对比逻辑:内层循环找到匹配项时将flag置为true,内层循环全部结束后,仅当flag为false时,才输出A中独有的SQL内容,自动去掉多余的调试输出和错误提示
  5. 输出内容时补回原SQL结尾的分号,保证输出格式和原始SQL一致

修改后的完整可运行脚本如下:

#!/bin/bash

# 初始化存储数组
first_array=()
second_array=()

# 读取A.sql,按分号拆分SQL
i=0
while IFS= read -rd ';' first_sql; do
  # 规范化SQL:统一空白格式,清理前后无效字符
  normalized=$(echo "$first_sql" | tr -s '[:space:]' ' ' | sed 's/^ *//;s/ *$//')
  # 跳过空内容
  [[ -n $normalized ]] && first_array[$i]="$normalized" && i=$((i+1))
done < A.sql
# 处理A.sql末尾无分号的最后一段内容
if [[ -n $first_sql ]]; then
  normalized=$(echo "$first_sql" | tr -s '[:space:]' ' ' | sed 's/^ *//;s/ *$//')
  [[ -n $normalized ]] && first_array[$i]="$normalized"
fi

# 读取B.sql,按分号拆分SQL
j=0
while IFS= read -rd ';' second_sql; do
  normalized=$(echo "$second_sql" | tr -s '[:space:]' ' ' | sed 's/^ *//;s/ *$//')
  [[ -n $normalized ]] && second_array[$j]="$normalized" && j=$((j+1))
done < B.sql
# 处理B.sql末尾无分号的最后一段内容
if [[ -n $second_sql ]]; then
  normalized=$(echo "$second_sql" | tr -s '[:space:]' ' ' | sed 's/^ *//;s/ *$//')
  [[ -n $normalized ]] && second_array[$j]="$normalized"
fi

# 对比两个数组,输出A有但B没有的SQL
for p in "${first_array[@]}"; do
  is_exist=false
  for q in "${second_array[@]}"; do
    if [[ $p == "$q" ]]; then
      is_exist=true
      break
    fi
  done
  # 仅当B中无匹配时,输出差异内容
  if [[ $is_exist == false ]]; then
    echo "$p;"
  fi
done
效果说明
  • 针对你提供的示例场景:A.sql包含4条SQL、B.sql包含3条SQL,脚本会正确输出Select * from subject;,和预期完全一致
  • 完全支持跨多行的长SQL拆分匹配,不会因为单条SQL跨4-5行、存在缩进/换行差异就误判
  • 兼容文件末尾SQL无分号的边界场景,不会丢失最后一段SQL内容
  • 自动忽略SQL之间的空白、换行格式差异,只要SQL语义一致就会判定为匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.12 15:27:02