这几天写了个多线程的数据抽取perl脚本,速度很快,可达到1G/m以上。可是今天做fastload加载时,被破了瓢冷水:
抽过来的所有的文件都无法正常的加载,表现的形式是我抽取的数据始终要比BOSS送过来的数据大那么一点点,但记录
条数没有异常。于是我开始了艰难的查错之旅:
2.用cygwin查看各条记录的长度,输出长度不对的行:
awk '{ if ( length($0) !=行字节数) {print $0;print NR} }' xxx.dat
结果令我失望,所有行的长度均正常;
3.编写一perl脚本,比较我抽取的数据文件和正确文件的差异:
#!/user/bin/perl
use strict;
use File::Basename;
use POSIX qw(strftime);
open(IN, "E:ETLDATAprocessQ01_CUST_PERSON_INFO_T_20090203.dat") or die "open error: $!";
my @x = ;
close (IN);
open(IN, "E:ETLDATAprocessQ01_CUST_PERSON_INFO_T_20090203_1.dat") or die "open error: $!";
my @y = ;
close (IN);
chomp(@y);
my $p = join('|', map{quotemeta} @y);
#print (grep /$p/, @x);
print (grep ! /$p/, @x);
五分钟后,运行完毕,结果令人沮丧,输出日志大小为0;
4.我开始怀疑是不可见字符引起的异常,可是这个怎么查呢?
5.新的一天开始了,有高手过来,机会难得,开问。高手就是高手,听了我的描述,他决定用UE查看文件的十六进制编码,
用UE打开,弹出窗口:"转换成DOS模式",点“是”,比较两文件的十六进制编码,发现完全一样!
怎么办呢?先看看大小差异有没有什么规律:
一行数据可见字符的长度为388*25538=9908744
正常:9934282 = 9908744 + 25538
异常:9959820 = 9934282 + 25538
也就是说正常情况下不可见字符数为每行1个,而我抽取的为每行2个
再用UE打开,弹出窗口:"转换成DOS模式",点“是”,比较两文件的十六进制编码,重点关注不可见的回车换行符,发现还是完全一样!怎么回事呢?突然想起BOSS的数据库环境为UNIX,是不是编码不一样呢?找到UE菜单中“DOS到UNIX”转换,转换格式,保存。发现大小变为正确值,fastload,成功。突然明白,查看十六进制编码完全一样的罪魁祸首在于惯性的点击UE弹出的"转换成DOS模式"。验证一下,点击弹出窗口的“否”,果然发现区别,抽取数据的回车换行的编码为“0A0D”,正确数据为“0D”。
结论:dos与unix在文件中换行字符的表现机置存在差异:
dos格式下,切换一行是二个字符的,由回车(od),换行(oa),文件尾部直接EOF(文件结束标志)
而unix下,切换一行,使用的是单换行符(oa),文件最后一行也会增加该字符,然后才是eof
验证如下:
windos下建一个文件,1.txt,输入:
afew
aef(到此打住)
使用ultraedit的十六进制查看,或者上传到unix机,使用:"xxd 文件名"以十六进制查看文件,结果如下:
0000000: 6166 6577 0d0a 6165 66 afew..aef
增加了Od,Oa二个字符
而在unix下,简单创建一个同样的文件:"vi 2.txt",输入
afew
aef(同样到此打住)
使用"xxd 2.txt" 查看:
0000000: 6166 6577 0a61 6566 0a afew.aef.
可以看到,第一行后边只有一个"oa" 换行符,同时最后一行也自动增加了oa字符
现在用wc查看下二个文件的情况:
>wc -l 1.txt 2.txt
1 2 9 1.txt
2 2 9 2.txt
3 4 18 total
可以看到,二个文件的字符数是一样的,这个上边已经分析.
使用UE转化工具dos2unix,功用是把dos的二个切换符转化成unix的单个字符
>dos2unix 1.txt
>wc 1.txt
1 2 8 1.txt
>xxd 1.txt
0000000: 6166 6577 0a61 6566 afew.aef
发现回车符已经被去掉了.,
同样使用转化工具unix2dos,功用是把unix下的单换行字符转化为dos下的二个字符:
>unix2dos 2.txt
>wc 2.txt
2 2 11 2.txt
>xxd 2.txt
0000000: 6166 6577 0d0a 6165 660d 0a afew..aef..
可以看到,二个单换行符已经转化成dos下的四个字符,文件大小也多了2个字符.
现在继续使用wc查看下这二个文件情况:
>wc 1.txt 2.txxt
1 2 8 1.txt
2 2 11 2.txt
3 4 19 total
现在文件的大小问题 ,已经换行符文题已经解决了,再来关注一下unix下一些工具所受到的影响 ,仔细看可以发现一个问题 :不管是什么格式的,在windows下生成的和在dos下生成的,行数都差一,dos下创建的文件最后一行哪里去了?没有统计到吗?
是的,的确没统计到,wc根据行未的oa字符判断的行数,所以结果是最后一行被忽略了.而dos2unix仅是对已有的0a/0d到oa之前的转化,对于windows下创建的文件进行dos2unix,也不会在最后一行里增加oa字符,所以即使用dos2unix后,文件wc结果也会少一行
同样受到影响的还有while语句
>while read line; do echo $line; done <1.txt
afew
可以看到,结果也只打出了一行,
sed就不受这个的影响了:
>sed 's/a/ccc/g' 1.txt
cccfew
cccef
再试awk命令:
>awk '{print $0}' 1.txt
afew
aef
也没有受到影响
目前常用到的shell命令,就是wc/while语句,受到影响.
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/16723161/viewspace-1016821/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/16723161/viewspace-1016821/