免费注册 查看新帖 |

Chinaunix

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

[文本处理] 求一个文件内容比较脚本(按指定列进行比较) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-11-27 15:56 |只看该作者 |倒序浏览
5可用积分
求一个文件内容比较脚本(按指定列进行比较)
awk、sed、perl、bash shell 都可以

本来想用hashmap来做,但是查了下好像shell没有相关信息

以下面fileA 、fileB 两个文件为例:
只比较列1、列2; 列3忽略不做比较
文件记录数不一样;
列分割符为"|";

A. 当fileA与fileB当前行的列2不相同时:
   1. 把fileA中的当前行记录写入diffA
   2. 把fileB中的当前行记录吸入diffB(如果当前行为空白则不写入)
B. 当fileA与fileB当前行的列2相同, 但列1不相同时:
   1. 把fileA中的当前行记录写入diffA
   2. 把fileB中的当前行记录吸入diffB
   
fileA (15行)内容:(# 后的内容为注释, 实际文件中不存在)
  1. A|02942|20121126111458  # 相同记录(忽略第3列)
  2. A|03055|20121126110255  # 相同记录(忽略第3列)
  3. A|08931|20121126133649  # 写入diffB(fileB没有该记录)
  4. A|08932|20121126133743  # 写入diffA(与fileB的列1不相同)
  5. A|27822|20121126212704  # 相同记录(忽略第3列)
  6. A|31520|20121126153305  # 写入diffB(fileB没有该记录)
  7. A|31612|20121126103716  # 写入diffB(fileB没有该记录)
  8. D|40439|20121126193846  # 写入diffA(与fileB的列1不相同)
  9. D|43223|20121126113926  # 写入diffB(fileB没有该记录)
  10. A|45789|20121126142204  # 写入diffB(fileB没有该记录)
  11. A|46651|20121126143730  # 写入diffB(fileB没有该记录)
  12. A|49212|20121126152429  # 写入diffB(fileB没有该记录)
  13. A|52009|20121126173141  # 写入diffB(fileB没有该记录)
  14. A|60524|20121126171733  # 写入diffA(与fileB的列1不相同)
  15. A|61257|20121126113339  # 写入diffA(与fileB的列1不相同)
复制代码
fileB (12行)内容:(# 后的内容为注释, 实际文件中不存在)
  1. A|02942|20071128200822  # 相同记录(忽略第3列)
  2. A|03055|20071128200827  # 相同记录(忽略第3列)
  3. D|08932|20071128201524  # 写入diffB(与fileA的列1不相同)
  4. D|13992|20091212125210  # 写入diffB(fileA没有该记录)
  5. D|21780|20071128202710  # 写入diffB(fileA没有该记录)
  6. A|27822|20071128203440  # 相同记录(忽略第3列)
  7. D|29558|20071128203708  # 写入diffB(fileA没有该记录)
  8. A|34079|20071128204308  # 写入diffB(fileA没有该记录)
  9. D|34619|20071128204330  # 写入diffB(fileA没有该记录)
  10. A|40439|20071128204933  # 写入diffB(与fileA的列1不相同)
  11. D|60524|20121126171733  # 写入diffB(与fileA的列1不相同)
  12. D|61257|20121126113339  # 写入diffB(与fileA的列1不相同)
复制代码
目标文件: diffA (# 后的内容为注释, 实际文件中不存在)
  1. A|08931|20121126133649  # fileB没有该记录
  2. A|08932|20121126133743  # 与fileB的列1不相同
  3. A|31520|20121126153305  # fileB没有该记录
  4. A|31612|20121126103716  # fileB没有该记录
  5. D|40439|20121126193846  # 与fileB的列1不相同
  6. D|43223|20121126113926  # fileB没有该记录
  7. A|45789|20121126142204  # fileB没有该记录
  8. A|46651|20121126143730  # fileB没有该记录
  9. A|49212|20121126152429  # fileB没有该记录
  10. A|52009|20121126173141  # fileB没有该记录
  11. A|60524|20121126171733  # 与fileB的列1不相同
  12. A|61257|20121126113339  # 与fileB的列1不相同
复制代码
目标文件: diffB (# 后的内容为注释, 实际文件中不存在)
  1. D|08932|20071128201524  # 与fileA的列1不相同
  2. D|13992|20091212125210  # fileA没有该记录
  3. D|21780|20071128202710  # fileA没有该记录
  4. D|29558|20071128203708  # fileA没有该记录
  5. A|34079|20071128204308  # fileA没有该记录
  6. D|34619|20071128204330  # fileA没有该记录
  7. A|40439|20071128204933  # 与fileA的列1不相同
  8. D|60524|20121126171733  # 与fileA的列1不相同
  9. D|61257|20121126113339  # 与fileA的列1不相同
复制代码

最佳答案

查看完整内容

#!/usr/bin/perlopen FILEA, "< $ARGV[0]";open FILEB, "< $ARGV[1]";while(){ chomp; push @fileA, $_;}while(){ chomp; push @fileB, $_;}(@fileA > @fileB) ? ($max=@fileA) : ($max=@fileB);for(0..$max-1){ $lineA=$fileA[$_]; $lineB=$fileB[$_]; $lineA=~s/^(\w+)\|(\w+)\|.*/$1$2/; $lineB=~s/^(\w+)\|(\w+)\|.*/$1$2/; if($lineA ne $lineB){ push @diffA, $fileA[$_]; push @diffB, $fileB[$_]; }}print "diffA:\n";fo ...

论坛徽章:
0
2 [报告]
发表于 2012-11-27 15:56 |只看该作者
#!/usr/bin/perl

open FILEA, "< $ARGV[0]";
open FILEB, "< $ARGV[1]";

while(<FILEA>){
        chomp;
        push @fileA, $_;
}

while(<FILEB>){
        chomp;
        push @fileB, $_;
}


(@fileA > @fileB) ? ($max=@fileA) : ($max=@fileB);


for(0..$max-1){
        $lineA=$fileA[$_];
        $lineB=$fileB[$_];
        $lineA=~s/^(\w+)\|(\w+)\|.*/$1$2/;
        $lineB=~s/^(\w+)\|(\w+)\|.*/$1$2/;
        if($lineA ne $lineB){
                push @diffA, $fileA[$_];
                push @diffB, $fileB[$_];
        }
}

print "diffA:\n";
for(@diffA){
        print "$_\n";
}
print "diffB:\n";
for(@diffB){
        print "$_\n";
}

$ ./diff.pl fileA.txt fileB.txt
diffA:
A|08931|20121126133649
A|08932|20121126133743
A|27822|20121126212704
A|31520|20121126153305
A|31612|20121126103716
D|40439|20121126193846
D|43223|20121126113926
A|45789|20121126142204
A|46651|20121126143730
A|49212|20121126152429
A|52009|20121126173141
A|60524|20121126171733
A|61257|20121126113339
diffB:
D|08932|20071128201524
D|13992|20091212125210
D|21780|20071128202710
A|27822|20071128203440
D|29558|20071128203708
A|34079|20071128204308
D|34619|20071128204330
A|40439|20071128204933
D|60524|20121126171733
D|61257|20121126113339

论坛徽章:
0
3 [报告]
发表于 2012-11-27 15:59 |只看该作者
helpid 发表于 2012-11-27 15:56
求一个文件内容比较脚本(按指定列进行比较)
awk、sed、perl、bash shell 都可以


源文件.zip (469 Bytes, 下载次数: 14)

论坛徽章:
32
处女座
日期:2013-11-20 23:41:20双子座
日期:2014-06-11 17:20:43戌狗
日期:2014-06-16 11:05:00处女座
日期:2014-07-22 17:30:47狮子座
日期:2014-07-28 15:38:17金牛座
日期:2014-08-05 16:34:01亥猪
日期:2014-08-18 13:34:25白羊座
日期:2014-09-02 15:03:55金牛座
日期:2014-11-10 10:23:58处女座
日期:2014-12-02 09:17:52程序设计版块每日发帖之星
日期:2015-06-16 22:20:002015亚冠之塔什干火车头
日期:2015-06-20 23:28:22
4 [报告]
发表于 2012-11-27 16:10 |只看该作者
第3行,列2不同,应该属于A这种情况吧?但是你两个都写入diffB是什么意思?

论坛徽章:
0
5 [报告]
发表于 2012-11-27 16:14 |只看该作者
以下是我的一个思路,还没法完全用awk写出来。很多地方需要帮助指正。
  1. # A文件
  2. fileA=fileA
  3. # B文件
  4. fileB=fileB

  5. # A的行数索引
  6. A_index=1
  7. # A的总记录数
  8. A_row_count=$(sed -n '$=' ${fileA})

  9. # B的行数索引
  10. B_index=1
  11. # B的总记录数
  12. B_row_count=$(sed -n '$=' ${fileB})

  13. awk -F'|'
  14.         -vA_index=${A_index}
  15.         -vA_row_count=${A_row_count}
  16.         -vB_index=${B_index}
  17.         -vB_row_count=${B_row_count}
  18.        
  19.         '
  20.         BEGIN
  21.         {
  22.                 i=1
  23.         }
  24.         while(i<NR)
  25.         {
  26.                 if(A_index>=A_row_count)
  27.                 {
  28.                         # 从fileB当前索引行到fileB最后一行的所有数据写入diffB
  29.                         for(j=B_index;j<=B_row_count;j++)
  30.                         {
  31.                                 print "B",B_index # 暂时没写出来
  32.                         }
  33.                         break;
  34.                 }
  35.                 else if(B_index>=B_row_count)
  36.                 {
  37.                         # 从fileA当前索引行到fileA最后一行的所有数据写入diffA
  38.                         for(j=A_index;j<=A_row_count;j++)
  39.                         {
  40.                                 print "A",A_index # 暂时没写出来
  41.                         }
  42.                         break;
  43.                 }
  44.                 else
  45.                 {
  46.                         a[NR]=$0 # 读取fileA的行数据(貌似不对)
  47.                         # 判断当前行是否为空
  48.                         if(length(a[NR])==0)
  49.                         {
  50.                                 A_index++
  51.                                 continue
  52.                         }
  53.                        
  54.                         b[NR]=$0 # 读取fileB的行数据(貌似不对)
  55.                         # 判断当前行是否为空
  56.                         if(length(b[NR])=0)
  57.                         {
  58.                                 B_index++
  59.                                 continue
  60.                         }
  61.                        
  62.                         A_type[NR]=$1;A_msisdn[NR]=$2 # 解析fileA的当前行第1列和第2列数据
  63.                         B_type[NR]=$1;B_msisdn[NR]=$2 # 解析fileB的当前行第1列和第2列数据
  64.                        
  65.                         # fileA的第2列 == fileB的第2列
  66.                         if(A_msisdn[NR]==B_msisdn[NR])
  67.                         {
  68.                                 # fileA的第1列 != fileB的第1列
  69.                                 if(A_type[NR]!=B_type[NR])
  70.                                 {
  71.                                         print A"$0" # fileA的当前行数据写入diffA(貌似不对)
  72.                                         print B"$0" # fileB的当前行数据写入diffB(貌似不对)
  73.                                 }
  74.                                 A_index++
  75.                                 B_index++
  76.                         }
  77.                         # fileA的第2列 > fileB的第2列
  78.                         else if(A_msisdn[NR]>B_msisdn[NR])
  79.                         {
  80.                                 print B"$0" # fileB的当前行数据写入diffB(貌似不对)
  81.                                 B_index++
  82.                         }
  83.                         # fileA的第2列 < fileB的第2列
  84.                         else
  85.                         {
  86.                                 print A"$0" # fileA的当前行数据写入diffA(貌似不对)
  87.                                 A_index++
  88.                         }
  89.                 }
  90.                 i++;
  91.         }
  92.         ' fileA fileB
复制代码

论坛徽章:
0
6 [报告]
发表于 2012-11-27 16:41 |只看该作者
  1. awk -F'|' 'ARGIND==1{a[$1$2]}ARGIND>1&&!($1$2 in a){print $0}' fileA fileB > diffA
  2. awk -F'|' 'ARGIND==1{a[$1$2]}ARGIND>1&&!($1$2 in a){print $0}' fileB fileA > diffB
复制代码
搞定了。awk 太强悍了。。。。

论坛徽章:
0
7 [报告]
发表于 2012-11-27 16:42 |只看该作者
awk -F'|' 'ARGIND==1{a[$1$2]}ARGIND>1&&!($1$2 in a){print $0}' fileA fileB > diffA
awk -F'|' 'ARGIND==1{a[$1$2]}ARGIND>1&&!($1$2 in a){print $0}' fileB fileA > diffB

论坛徽章:
0
8 [报告]
发表于 2012-11-27 17:25 |只看该作者
  1. # 只在file1中有的行
  2. awk -F'|' 'ARGIND==1{a[$1$2]}ARGIND>1&&!($1$2 in a){print $0}' file2 file1
  3. # 只在file2中有的行
  4. awk -F'|' 'ARGIND==1{a[$1$2]}ARGIND>1&&!($1$2 in a){print $0}' file1 file2
  5. # 同时在file1和file2中的行
  6. awk -F'|' 'ARGIND==1{a[$1$2]}ARGIND>1&&($1$2 in a){print $0}' file1 file2
复制代码
以上方法参照了jomenxiao的文章:
http://blog.chinaunix.net/uid-25149914-id-3091426.html

论坛徽章:
0
9 [报告]
发表于 2012-11-27 21:10 |只看该作者
回复 6# helpid


    DS,可以解释一下ARGIND==1 和ARGIND>1 究竟是什么意思??

论坛徽章:
0
10 [报告]
发表于 2012-11-27 21:59 |只看该作者
A|27822|20121126212704  # 相同记录(忽略第3列)

This line is not the same between A and B, A is in line #5, B is in line #6
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP