看到文章标题,你可能已经想到了解决之道,也许会使用高级编程语言、操作系统命令或Excel等方法,本文旨在分享一条操作系统命令,帮助你较为快速的找出大CSV文件中那些列数不一样的行。
为什么会有这样的需求呢?当然这是我自己的需求,也许会对你有所帮助。在某次转储Oracle数据库(Oracle Database 19c)中某张表的数据时,客户要求将数据导出为CSV格式。最开始想到的方法就是使用SQL*Plus提供的spool功能;后面又想,能不能使用外部表来卸载表数据,但此方法仅能在使用ORACLE_DATAPUMP访问驱动时,才拥有卸载表数据的功能,且仅能将表数据卸载为数据泵文件格式(以XML格式组织数据),例如,你可以执行如下SQL来卸载表T1的数据:
create table t1_unload organization external ( type oracle_datapump default directory tmp access parameters ( version '11.2.0' ) location ('t1.dat') ) as select * from t1;
复制
上述命令中的version访问参数,相当于是expdp中的version命令选项,如此,你便可以在较低版本的Oracle数据库中加载从较高版本中卸载的数据文件。当然你也可以使用图形界面客户端工具将表数据导出为CSV格式,这里也分享一下使用SQL*Plus将数据导出为csv格式的命令:
cat spool.sql set term off verify off feedback off pagesize 0 set heading off set markup csv on delimiter ',' quote on spool /home/oracle/t1.csv select * from t1; spool off cat execute.sh #!/bin/bash source /home/oracle/.bash_profile sqlplus / as sysdba <<EOF @/home/oracle/spool.sql EOF
复制
为啥还要加一个shell脚本,明白人都明白,小编也是尝过了一点“甜头”,有些表数据的导出可不是一下就结束了哦,所以我一律放后台跑,以上只是做一个铺垫,接下来才是本文要重点介绍的部分。
数据导出完成之后,通过行数比对,发现CSV文件的行数(wc -l)大于表数据行数,说明导出数据存在跨行问题。首先可以明确的一点是,正常情况下,每一行的列数是一致的,既然存在数据跨行,那么也就说明存在列数不一样的行,现在的关键是找出这些行,如下便是我要分享的命令:
awk -F, '{if(NF<5) {print NR,$0}}' t1.csv | more
复制
上述命令假设表或视图有5列数据,跨行数据在文件中通常是连续存放的,通过执行上述命令,我们便可找出那些列数小于5的行号,随后就可通过vim编辑器进行定位(在命令模式下:敲击键“行号gg”,即可定位至指定的行)调整。CSV数据尽量是规范的,数据中未包含“,”符号,如果数据中包含了“,”符号,上述命令也是适用的,因为我们只是找列数小于正常值的行。你也可以对命令加以调整以适用其它特殊需求,例如:查看csv文件中列数不是5的行:
awk -F, '{print NF}' t1.csv | grep -nv 5
复制
其实这些就是对awk命令用法的分享,虽然不是很高级,但希望对你有帮助,我亲爱的朋友。