zoukankan      html  css  js  c++  java
  • 如何使用shell脚本快速排序和去重文件数据

      前面写过一篇通过shell脚本去重10G数据的文章,见《用几条shell命令快速去重10G数据》。然而今天又碰到另外一个业务,业务复杂度比上次的单纯去重要复杂很多。找了很久没有找到相应的办法,于是用shell脚本程序去处理。具体业务逻辑:

      1、首先根据给定指定进行排序

      2、排序后对给定字段进行去重,去重的规则如下:

        a)排序后如果相邻N行给定字段值相同的行数不超过两行,则两行都保留。

        a)排序后如果相邻N行给定字段值相同的行数超过两行,则保留首行和尾行。

      就这样一个业务逻辑,其实看起来并不是太难。但是问题来了,怎么才能在10~20G的数据中快速地进行处理呢?网上找了很久没找到相应的处理办法,于是先用一种相对笨的办法实现。

      测试数据:

    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    A0223EE1IDJDJ2938X39284BE,20080304041155 ,OQQQQ54,876F0,88888120,727271202,ss
    A0223EE1IDJDJ2938X39284BE,20080304041155 ,OQQQQ54,876F0,88888120,727271202,ss

      shell脚本:

    if [ "$#" != "2" ]; then
            echo "Usage: 参数1:文件路径,参数2:文件名。"
            exit
    fi
    #源文件所在目录
    filepath=$1
    #源文件绝对路径
    orgfile=$filepath"/"$2
    #合并字段后的临时文件
    #mergerfile="$orgfile"_merge.txt
    #排序后的临时文件
    sortfile="$orgfile"_sort.txt
    #最终结果文件
    result_unique="$orgfile"_result_unique.txt
    echo "">$result_unique
    #echo "文件:$orgfile"
    #echo "开始合并字段..."
    #awk 'BEGIN{ FS=",";}{ print $1","$2","$3","$4","$5","$6","$7","$1$3$4 }' $orgfile > $mergerfile
    #echo "字段合并结束..."
    
    echo "文件排序 start..."
    #sort -t $"," -k 1,1 -k 9,9 $mergerfile >$sortfile
    sort -t $"," -k 1,2 $orgfile >$sortfile
    echo "文件排序 end..."
    
    
    printf "***********文件比较 start**************************
    "
    echo "while read line <$sortfile"
    cnt=0
    #首行
    firstline=""
    #尾行
    lastline=""
    #上一次比较的key
    lastKey=""
    #文件行数
    linecount=`sed -n '$=' $sortfile`
    i=1
    echo "linecount=========>>>>>>>$linecount"
    while read line || [[ -n "$line" ]];
    do
      echo $line;
      #合并需要比较的字段
      compare=`echo "$line"|awk -F ',' '{print $1$3$4}'`
      echo "compare=====$compare"
      #判断字符串是否相等
      if [ "$i" != "$linecount" -a "$lastKey" = "$compare" ];then
        echo "[ = ]"
        cnt=$(expr $cnt + 1)
        lastline="$line"
      else
        #首次进来
        if [ "$firstline" = "" ];then
            firstline=$line
            cnt=1
            #echo "$firstline" >> $result_unique
        fi
        #echo "----$i---------------->>>>>>>>>>>$cnt"
        if [ $cnt -gt 1 -o "$i" == "$linecount" ];then
            echo "----$i---------------->>>>>>>>>>>$cnt"
    
            if [ "$i" != "$linecount" -a "$lastline" != "" ];then
                    echo "$lastline" >> $result_unique
                    echo "$line" >> $result_unique
            fi
    
            # 最后一行的特殊处理
            if [ "$i" == "$linecount" ];then
                    echo "================last line==================="
                    echo "$line" >> $result_unique
            fi
    
            firstline="$line"
            lastline="$line"
            cnt=1
        elif [ $cnt -eq 1 ];then
            firstline=$line
            lastline="$line"
            cnt=1
            echo "$lastline" >> $result_unique
        fi
      fi
      # 对比key
      lastKey="$compare"
      let i++
    done <$sortfile
    
    echo "*******************文件 $orgfile 处理结束***************************"
    echo "*******************结果文件 $result_unique ***************************"
    exit

      给脚本添加执行权限:

    chmod +x uniquefile.sh

      执行shell脚本

    sh ./uniquefile.sh ./文件路径 文件名

      结果:

    [root@xddsdsdsddssd ~]# sh uniquefile.sh ./ testfile.csv 
    文件排序 start...
    文件排序 end...
    ***********文件比较 start**************************
    while read line <.//testfile.csv_sort.txt
    linecount=========>>>>>>>6
    A0223EE1IDJDJ2938X39284BE,20080304041155 ,OQQQQ54,876F0,88888120,727271202,ss
    compare=====A0223EE1IDJDJ2938X39284BEOQQQQ54876F0
    A0223EE1IDJDJ2938X39284BE,20080304041155 ,OQQQQ54,876F0,88888120,727271202,ss
    compare=====A0223EE1IDJDJ2938X39284BEOQQQQ54876F0
    [ = ]
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    compare=====F250A4FFIDJDJ2938X39252E7OQQQQB88769E
    ----3---------------->>>>>>>>>>>2
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    compare=====F250A4FFIDJDJ2938X39252E7OQQQQB88769E
    [ = ]
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    compare=====F250A4FFIDJDJ2938X39252E7OQQQQB88769E
    [ = ]
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    compare=====F250A4FFIDJDJ2938X39252E7OQQQQB88769E
    ----6---------------->>>>>>>>>>>3
    ================last line===================
    *******************文件 .//testfile.csv 处理结束***************************
    *******************结果文件 .//testfile.csv_result_unique.txt ***************************

      最终结果文件:

    [root@wewewwew ~]# more testfile.csv_result_unique.txt 
    
    A0223EE1IDJDJ2938X39284BE,20080304041155 ,OQQQQ54,876F0,88888120,727271202,ss
    A0223EE1IDJDJ2938X39284BE,20080304041155 ,OQQQQ54,876F0,88888120,727271202,ss
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss
    F250A4FFIDJDJ2938X39252E7,20080304041348 ,OQQQQB8,8769E,88888626,727218105,ss

      时间比较赶,先这样实现吧。哪位亲们有好的办法请告诉我。

  • 相关阅读:
    laravel观察者模式使用及注意事项
    所有CM_消息的说明
    编写Delphi控件属性Stored和Default的理解及应用
    DBGrid上设置选择项
    Enter键使用作Tab键
    delphi 向Windows窗口发送Alt组合键的问题
    DBGridEh用法总结三(PivotGrid的汉化)
    delphi FastReport快速入门
    fastreport打印空白行的方法
    VC对话框如何添加WM_ERASEBKGND消息(OnEraseBkgnd函数)及对话框使用位图背景并透明
  • 原文地址:https://www.cnblogs.com/rwxwsblog/p/5638393.html
Copyright © 2011-2022 走看看