Shell脚本校验竖线分隔文件带+号表头失效如何修改?
Shell脚本|分隔文件表头校验特殊字符兼容修复方案
需求说明
- 校验场景:文件上传后、SQLLDR处理文件前
- 校验规则:|分隔文件的表头数量、名称、排列顺序必须和预期值完全匹配
- 预期表头:
- Activity
- Activity+ ID
- Description
- Status
- 异常现象:包含
+号的表头始终提示校验不通过,移除+后校验功能正常
原代码核心问题
- 循环逻辑完全错误:你定义的
header是值为4的整数变量,for item1 in "${header[@]}"实际是遍历数字4,根本没有用到读取到的文件表头数组做比对 - 表头分割逻辑存在隐患:直接
fldarray=( $line )的写法容易触发特殊字符分词、扩展规则,+号属于特殊字符会被异常处理 - 匹配逻辑不符合要求:双重循环的比对方式无法校验表头排列顺序,还会产生大量误判
修复后可兼容特殊字符的代码
# 直接定义预期表头数组,自动计算预期数量避免变量不同步 expected_fields=( "Activity" "Activity+ ID" "Description" "Status" ) expected_count=${#expected_fields[@]} # 遍历待校验文件 for file in "Test File.csv"; do # 读取第一行表头,避免转义字符被自动处理 IFS= read -r header_line < "$file" # 按|分割表头到数组,用read方式分割避免特殊字符被异常解析 IFS='|' read -ra actual_fields <<< "$header_line" actual_count=${#actual_fields[@]} # 第一步校验表头数量 if (( actual_count != expected_count )); then printf "错误:文件'%s'表头数量不匹配,预期%d个,实际%d个\n" "$file" "$expected_count" "$actual_count" continue fi # 第二步按顺序逐字段校验内容 local mismatch=() for idx in "${!expected_fields[@]}"; do if [[ "${actual_fields[$idx]}" != "${expected_fields[$idx]}" ]]; then mismatch+=("第$((idx+1))列不匹配:预期'${expected_fields[$idx]}',实际'${actual_fields[$idx]}'") fi done # 输出校验结果 if (( ${#mismatch[@]} > 0 )); then printf "错误:文件'%s'表头校验不通过,错误详情:\n" "$file" printf -- "- %s\n" "${mismatch[@]}" else printf "文件'%s'表头校验通过\n" "$file" fi printf "\n\n" done
关键修复点说明
- 采用
IFS='|' read -ra actual_fields <<< "$header_line"的方式分割表头,完全规避+、空格等特殊字符被bash分词逻辑错误处理的问题 - 改成按下标逐位比对的逻辑,同时校验表头内容和排列顺序,完全符合需求
- 所有变量引用都加了双引号,避免特殊字符、空格导致的解析异常
- 去掉了冗余的整数变量定义,直接取预期表头数组长度作为校验标准,避免变量修改不同步的问题
内容的提问来源于stack exchange,提问作者Pat
相关产品推荐
相关产品推荐

