由于生产数据很多人工录入数据,很不规范,导致有些接口数据中经常出现分隔符,换行符等。一般情况下需要写一些处理转换程序,如果考虑稳定健壮运行,可以用java等语言编写。但有时候需要临时处理一些数据的时候,还要用java就有点笨重了。这时候脚本语言就像瑞士军刀,很有用途。
我们的需求是:原文件根据分隔符分割后列数是固定的(格式化数据),把原文件中换行错位的数据尽可能恢复。也就是错位的时候把下一行挪到上一行来。
举个栗子:接口原文件格式如下:
1 a b c
d e f
2 a b c d e f
3 a b c d e f
4 a b c d
e f
5 a b c d e f
6 a b c
7 a b c d e f
8 a b
c d
e f
9 a b c d e f
原数据说明如下:
1 a b c #第1行
d e f #第1行错位数据
2 a b c d e f #第2行正常数据
3 a b c d e f #第3行正常数据
4 a b c d #第4行
e f #第4行错位数据
5 a b c d e f #第5行正常数据
6 a b c #第6行异常数据 --其实这种数据一般不会有啦
7 a b c d e f #第7行正常数据
8 a b #第8行
c d #第8行错位数据
e f #第8行错位数据
9 a b c d e f #第9行正常数据
输出要求:
1 a b c d e f
2 a b c d e f
3 a b c d e f
4 a b c d e f
5 a b c d e f
6 a b c
7 a b c d e f
8 a b c d e f
9 a b c d e f
我喜欢用linux较原生的命令,这里主要用awk实现:
awk 'BEGIN{FS="\t";TNF=0;TMP="";SIZE=7};{if(TNF==0 && NF==SIZE){ print $0 }else if(NF==SIZE){ print TMP"\n"$0; TNF=0; TMP=""; }else if(TNF+NF-1>=SIZE){ print TMP" "$0; TNF=0; TMP=""; }else if(length(TMP) > 0){ TMP=TMP" "$0; TNF+=NF-1; }else{ TMP=$0; TNF=NF; }}' myFile.txt
命令注解如下(命令逻辑复杂在要考虑多行错位,就像我栗子中的第8行):
awk 'BEGIN{FS="\t";TNF=0;TMP="";SIZE=7}; #这里声明原字段分隔符,以及一些变量(可以理解为缓存),以及字段列数应该为多少
{
if(TNF==0 && NF==SIZE){ #TNF是Begin里声明的变量,NF是awk的隐式变量:域数
print $0 #没有缓存且当前记录没有问题时,直接打印
}else if(NF==SIZE){ #当前记录没有问题,且有缓存时,先打印缓存再打印当前记录
print TMP"\n"$0;
TNF=0;
TMP="";
}else if(TNF+NF-1>=SIZE){ #当前记录列数+缓存列数 大于固定列数时打印缓存
print TMP" "$0; #我这里还多拼了个空格(替代原来的换行符,下同)
TNF=0;
TMP="";
}else if(length(TMP) > 0){ #之前有缓存,则拼接
TMP=TMP" "$0;
TNF+=NF-1;
}else{ #没缓存啦,直接赋值
TMP=$0;
TNF=NF;
}
}‘ myFile.txt #我要处理的文件