免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 43070 | 回复: 12
打印 上一主题 下一主题

[文本处理] 如何处理宽度固定的列 [复制链接]

论坛徽章:
2
技术图书徽章
日期:2013-12-17 13:52:152015亚冠之萨济拖拉机
日期:2015-07-19 11:07:52
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2016-07-29 19:42 |只看该作者 |倒序浏览
有一个通过sqlplus spool出来的文本文件,列的宽度是固定的,现在要求还原成SQL文本
  1. 12345678 123456 1234 12345678 123456
  2. abcd     abc3        7834     4556  
  3. 34       45     dfd  444            
复制代码
以上文件有5列,每列之间用一个空格分开,注意可能有些列的值为空(比如第二行第三列),列的定义如下:

第1列: char 8
第2列: char 6
第3列: char 4
第4列: number 8
第5列: char 6

要求转换成SQL语句,比如第二行转换后为:

insert into t values('abcd','abc3',null,7834,'4556');

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
2 [报告]
发表于 2016-07-29 19:57 |只看该作者
看着列的对其方式倒是挺齐的, 就是不知道空列如何进行判断.

论坛徽章:
2
技术图书徽章
日期:2013-12-17 13:52:152015亚冠之萨济拖拉机
日期:2015-07-19 11:07:52
3 [报告]
发表于 2016-07-29 20:45 |只看该作者
二楼的,列都是定长的,不够宽度的都用空格补齐了,因此只需要按照列宽度从相应位置截取,去掉尾部的空格即可。
比如第二行第三列,从第17个char向后截取4位,就代表第三列的值,结果是4个空格,去掉尾部所有空格,就变成空了。

论坛徽章:
2
技术图书徽章
日期:2013-12-17 13:52:152015亚冠之萨济拖拉机
日期:2015-07-19 11:07:52
4 [报告]
发表于 2016-07-29 22:27 |只看该作者
加了个班,搞定了
  1. BEGIN{
  2.   FIELDWIDTHS="9 7 5 9 7"
  3. }
  4. {
  5.   for (i=1;i<=NF;i++){
  6.     gsub(/\s*$/,null,$i)
  7.     $i=$i==null?"null":"'"$i"'"
  8.   }
  9.   printf("insert into t values(%s,%s,%s,%s,%s);\n",$1,$2,$3,$4,$5)
  10. }
复制代码

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
5 [报告]
发表于 2016-07-29 22:28 |只看该作者
3 楼的, 试下:
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. while (<DATA>){
  5.     my ($last_pos, @aData) = 0;
  6.     foreach my $num ((8, 6, 4, 8, 6)){
  7.         my $val = substr ($_, $last_pos, $num) =~ s/\s+//r;
  8.         push (@aData, length ($val) ? qq ('$val') : 'null');
  9.         $last_pos += $num + 1;
  10.     }
  11.     print "insert into t values(", join (",", @aData), ");\n";
  12. }

  13. __DATA__
  14. 12345678 123456 1234 12345678 123456
  15. abcd     abc3        7834     4556
  16. 34       45     dfd  444
复制代码
perl abc.pl
----------------------------------------------------------------
insert into t values('12345678','123456','1234','12345678','123456');
insert into t values('abcd','abc3',null,'7834','4556');
insert into t values('34','45','dfd','444',null);

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
6 [报告]
发表于 2016-07-29 22:44 |只看该作者
我猜你还得再加加班, 把问题先搞定再说.

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
7 [报告]
发表于 2016-07-29 22:52 |只看该作者
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. my @aWidth = (8, 6, 4, 8, 6);
  5. while (<DATA>){
  6.     my ($last_pos, @aData) = 0;
  7.     while (my ($idx, $leng) = each @aWidth){
  8.         my $v = substr ($_, $last_pos, $leng) =~ s/\s+//r;
  9.         push (@aData, length ($v) ? do {$idx != 3 ? qq ('$v') : $v} : 'null');
  10.         $last_pos += $leng + 1;
  11.     }
  12.     print "insert into t values(", join (",", @aData), ");\n";
  13. }

  14. __DATA__
  15. 12345678 123456 1234 12345678 123456
  16. abcd     abc3        7834     4556
  17. 34       45     dfd  444
复制代码
perl abc.pl
---------------------------------------------------------------------------------------------------------------
insert into t values('12345678','123456','1234',12345678,'123456');
insert into t values('abcd','abc3',null,7834,'4556');
insert into t values('34','45','dfd',444,null);

评分

参与人数 1信誉积分 +50 收起 理由
rm-rf + 50 很给力!

查看全部评分

论坛徽章:
2
技术图书徽章
日期:2013-12-17 13:52:152015亚冠之萨济拖拉机
日期:2015-07-19 11:07:52
8 [报告]
发表于 2016-07-29 22:53 |只看该作者
sunzhiguolu 发表于 2016-07-29 22:44
我猜你还得再加加班, 把问题先搞定再说.


基本上搞定了,number型的还有些缺陷,number类型的insert不能加单引号,我的那个脚本也有一样的问题。
看来得区分number和string的。

论坛徽章:
28
15-16赛季CBA联赛之八一
日期:2016-02-22 19:10:4215-16赛季CBA联赛之深圳
日期:2016-12-01 10:34:0415-16赛季CBA联赛之新疆
日期:2016-12-07 10:24:2915-16赛季CBA联赛之同曦
日期:2016-12-15 12:06:43CU十四周年纪念徽章
日期:2016-12-18 13:03:4415-16赛季CBA联赛之吉林
日期:2017-01-03 15:52:2515-16赛季CBA联赛之辽宁
日期:2017-01-04 14:58:2415-16赛季CBA联赛之辽宁
日期:2017-01-15 09:42:512016科比退役纪念章
日期:2017-02-06 17:21:50黑曼巴
日期:2017-02-10 15:46:1215-16赛季CBA联赛之上海
日期:2017-03-18 10:14:5415-16赛季CBA联赛之青岛
日期:2017-03-18 22:00:44
9 [报告]
发表于 2016-07-29 22:58 |只看该作者
本帖最后由 moperyblue 于 2016-07-29 22:59 编辑

more file
  1. 12345678 123456 1234 12345678 123456
  2. abcd     abc3        7834     4556  
  3. 34       45     dfd  444            
复制代码
  1. awk 'BEGIN{
  2.     s="12345678 123456 1234 12345678 123456"
  3.     for(i=1;i<=length(s);i++){
  4.         if(substr(s,i,1)==" ")a[i]
  5.     }
  6. }
  7. NR>1{
  8.     for(i in a){
  9.       $0=gensub(/./,"@",i)
  10.   }
  11.   gsub(/ *@ */,"@")
  12.   gsub(/^ *| *$/,"")
  13.   len=split($0,b,"@")
  14.   for(i=1;i<=len;i++){
  15.     if(b[i]==""){
  16.         b[i]="null"
  17.         }else if(i!=4){
  18.             b[i]="\x27"b[i]"\x27"
  19.         }
  20.     }
  21.     printf "insert into t values("
  22.         for(i=1;i<=len;i++){
  23.             printf  (i==1?"":",")b[i]
  24.         }
  25.         printf ");\n"
  26. }' file
复制代码
insert into t values('abcd','abc3',null,7834,'4556');
insert into t values('34','45','dfd',444,null);

论坛徽章:
307
程序设计版块每周发帖之星
日期:2016-04-08 00:41:33操作系统版块每日发帖之星
日期:2015-09-02 06:20:00每日论坛发贴之星
日期:2015-09-02 06:20:00程序设计版块每日发帖之星
日期:2015-09-04 06:20:00每日论坛发贴之星
日期:2015-09-04 06:20:00每周论坛发贴之星
日期:2015-09-06 22:22:00程序设计版块每日发帖之星
日期:2015-09-09 06:20:00程序设计版块每日发帖之星
日期:2015-09-19 06:20:00程序设计版块每日发帖之星
日期:2015-09-20 06:20:00每日论坛发贴之星
日期:2015-09-20 06:20:00程序设计版块每日发帖之星
日期:2015-09-22 06:20:00程序设计版块每日发帖之星
日期:2015-09-24 06:20:00
10 [报告]
发表于 2016-07-29 23:02 |只看该作者
基本上搞定了,number型的还有些缺陷,number类型的insert不能加单引号,我的那个脚本也有一样的问题。
看来得区分number和string的。

还是你老兄会解释, 还能有基本搞定了这词儿.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP