Bash脚本处理CSV时echo输出字段意外换行问题修复
换行问题根因
三个字段单独输出到新行是以下原因叠加导致:
- 提取d59(域名TLD)、d17(注册人国家)、d60(联系电话)的子命令(awk/sed/cut/tr)默认会在输出末尾添加换行符,变量捕获时如果没有主动删除换行/回车符,拼接主行时换行符会被保留,直接把后续字段挤到新行。
- 大体积Whois CSV多为Windows平台导出,默认带
\r\n格式的CRLF换行,while read默认不会自动处理行尾的\r字符,隐形回车符会导致字段输出时意外断行。 - 逐行读取时如果未加
-r参数,字段内的反斜杠会被识别为转义符,也可能触发行结构错乱。
修正方案
快速修复现有while循环写法
不需要重构逻辑的前提下,做三处改动即可解决断行:
- 读取行时加
-r参数,禁止反斜杠转义,读取后先统一删除行尾的\r回车符 - 所有单独提取的字段,捕获后强制删除所有
\n/\r换行类字符 - 拼接完成后统一单次写入,不要分多次echo追加
参考修正后的循环片段:
#!/bin/bash # 清空目标文件 > abc.csv # 逐行读取加-r参数,管道先去掉所有CR回车 cat 源whois.csv | tr -d '\r' | while read -r line do # 原有主字段清洗逻辑保持不变,下面是三个易断行字段的提取写法 # 提取TLD(d59),提取后强制删除所有换行 d59=$(echo "$line" | awk -F',' '{print $59}' | tr -d '\n\r') # 提取注册人国家(d17),提取后强制删除所有换行 d17=$(echo "$line" | awk -F',' '{print $17}' | tr -d '\n\r') # 提取联系电话(d60),同时删除非数字/加号的特殊字符,强制删换行 d60=$(echo "$line" | awk -F',' '{print $60}' | tr -cd '0-9+\n\r' | tr -d '\n\r') # 把你原有清洗完成的主字段替换到下面的main_part变量位置 main_part="之前清洗好的其他字段用逗号拼接的结果" # 单次整行写入,不要分开echo echo "${main_part},${d59},${d17},${d60}" >> abc.csv done
大文件高性能处理方案
如果CSV体积超过1G,while循环嵌套多子进程的写法处理速度极慢,建议用单次awk完成全量清洗,从根源避免多子进程带来的换行问题,处理速度会提升50~200倍:
#!/bin/bash awk -F',' ' BEGIN {OFS=","} { # 逐字段清洗:去掉首尾双引号、删除字段内的逗号 for(i=1;i<=NF;i++) { gsub(/^"|"$/,"",$i) gsub(/,/,"",$i) } # 提取d59 TLD:如果第59列不是直接存的TLD,就替换成域名所在列做split提取 split($59, tld_seg, ".") d59 = tld_seg[length(tld_seg)] gsub(/[\r\n]/,"",d59) # 提取d17注册人国家,清理非字母字符和换行 d17 = $17 gsub(/[\r\n]|[^a-zA-Z]/,"",d17) # 提取d60联系电话,清理特殊字符和换行 d60 = $60 gsub(/[\r\n]|[^0-9+]/,"",d60) # 按你需要的顺序替换下面的字段序号即可 print $1,$2,$3,$5,$10,d59,d17,d60 } ' 源whois.csv > abc.csv
结果校验
处理完成后执行以下命令校验,如果输出结果为1,说明所有行字段数一致,没有断行问题:
awk -F',' '{print NF}' abc.csv | sort -nu | wc -l
内容的提问来源于stack exchange,提问作者Amit Singh
相关产品推荐
相关产品推荐

