Chinaunix

标题: 配对-格式调整 [打印本页]

作者: yinyuemi    时间: 2012-04-08 11:12
标题: 配对-格式调整
本帖最后由 yinyuemi 于 2012-04-08 14:38 编辑

最近坛里有些冷,任何方法都欢迎,sed,awk,perl ……

输入:

2       aaa
3       aaa
4       aaa
5       aaa
6       aaa
7       aaa
8       aaa
9       bbb
10      bbb
11      bbb
12      bbb
13      bbb
14      bbb
15      bbb

17      aaa
18      aaa
19      aaa
20      bbb
21      bbb
22      bbb

24      aaa
25      bbb

27      aaa
28      aaa
29      bbb
30      bbb


输出:

2 aaa 9 bbb
3 aaa 10 bbb
4 aaa 11 bbb
5 aaa 12 bbb
6 aaa 13 bbb
7 aaa 14 bbb
8 aaa 15 bbb

17 aaa 20 bbb
18 aaa 21 bbb
19 aaa 22 bbb

24 aaa 25 bbb
27 aaa 29 bbb
28 aaa 30 bbb


最后我会对大家的code进行测试,把执行效率的测试结果贴出了~(见14楼

作者: jiejie455    时间: 2012-04-08 12:01
本帖最后由 jiejie455 于 2012-04-08 12:01 编辑
  1. awk '{if(a[$2]){a[$2]=a[$2]" "$1}else{a[$2]=$1}}END{split(a["aaa"],c," ");split(a["bbb"],d," ");for(i=1;i<=length(c);i++){print c[i]" aaa "d[i]" bbb"}}' data
复制代码

作者: arthurscfd    时间: 2012-04-08 12:38
#!/bin/bash -
#-----------------------------------------------------------------------------
#          FILE: compose.sh
#         USAGE: ./compose.sh  txt
#
#        AUTHOR: moo (God helps those who help themselves)
#  ORGANIZATION:
#       CREATED: 2012-04-08 12:33:31 CST
#      REVISION: 1.0
#-----------------------------------------------------------------------------
cat <<-txthere > txt
2       aaa
3       aaa
4       aaa
5       aaa
6       aaa
7       aaa
8       aaa
9       bbb
10      bbb
11      bbb
12      bbb
13      bbb
14      bbb
15      bbb
17      aaa
18      aaa
19      aaa
20      bbb
21      bbb
22      bbb
24      aaa
25      bbb
27      aaa
28      aaa
29      bbb
30      bbb
txthere

list=(
    2 15
    17 22
    24 25
    27 30
)

fn_main ()
{


    for (( CNTR=0; CNTR<${#list[@]}; CNTR+=2 )); do
        head=${list[$CNTR]}
        tail=${list[(($CNTR+1))]}

        # echo $head $tail

        sec=` cat txt | sed -n -e  "/^${head}\>/,/^${tail}\>/ p"`
        line=`echo "$sec" | wc -l`
        # echo $line

        echo "$sec" | awk -v line=$line '{
            if (NR <= line/2) {
                txt[NR]=$0
            } else {
                print txt[NR-line/2], $0
            }
        }'
    done
}

fn_main txt


# 感觉不完美,抛砖
作者: yinyuemi    时间: 2012-04-08 12:44
回复 3# arthurscfd


    如果输入的文本有很多行的话,list 数组缺少通用性
作者: arthurscfd    时间: 2012-04-08 12:52
回复 2# jiejie455


    很精辟,学习ing
作者: jason680    时间: 2012-04-08 12:53
回复 1# yinyuemi

$ perl -lane '{push(@a,"@F") if($F[-1] eq "aaa");print shift @a," @F" if($F[-1] eq "bbb")}' FILE
   
作者: arthurscfd    时间: 2012-04-08 12:55
回复 4# yinyuemi


    是的,最近写东西有点不动大脑,看到问题就只想快点弄出来
作者: yinyuemi    时间: 2012-04-08 13:01
回复 6# jason680


    8错!这个效率应该很高~
作者: mpstat    时间: 2012-04-08 13:02
  1. sed -rn ':a;N;/aaa$/ba;/bbb$/{s/^([^\n]+)(.*)\n([^\n]+)$/\1 \3\2/;P;D}'
复制代码

作者: winway1988    时间: 2012-04-08 13:05
  1. awk '/aaa/{a[++na]=$0;next}/bbb/{b[++nb]=$0}END{for(i=1;i<=na||i<=nb;i++)print a[i]?a[i]:"",b[i]?b[i]:""}'
复制代码

作者: yinyuemi    时间: 2012-04-08 13:07
回复 9# mpstat


    相当犀利, 效率应该也很高~
作者: yinyuemi    时间: 2012-04-08 13:10
回复 10# winway1988


    非常好,可以再进一步想下如何不在END部分打印结果,这样效率会更好~
作者: mpstat    时间: 2012-04-08 13:31
本帖最后由 mpstat 于 2012-04-08 13:34 编辑

回复 11# yinyuemi

  1. export l=10000;seq $l|awk -va=$l 'BEGIN{srand();}{v=int(rand()*100);v=(a-NR)>2*v?v:int((a-NR)/2); for(i=0;i<v;++i){getline; print NR,"aaa"};for(i=0;i<v;++i){getline;print NR,"bbb"};}' > cc
复制代码
生成你的文件,改一下10000测测效率
作者: yinyuemi    时间: 2012-04-08 14:21
本帖最后由 yinyuemi 于 2012-04-08 14:37 编辑

回复 13# mpstat


    Thanks!
测试结果如下:


  1. 环境:cygwin
  2. CYGWIN_NT-5.1 version 1.7.11

  3. time awk -f jiejie455.awk testfile >/dev/null

  4. real    0m2.180s
  5. user    0m2.030s
  6. sys     0m0.124s

  7. time perl -lane '{push(@a,"@F") if($F[-1] eq "aaa");print shift @a," @F" if($F[-1] eq "bbb")}' testfile >/dev/null

  8. real    0m0.830s
  9. user    0m0.718s
  10. sys     0m0.061s

  11. 参考jason680的code略作修改,如下
  12. cat jason680_m.pl
  13. #!/bin/perl
  14. use strict;
  15. my @F;
  16. my @a;
  17. open(f,"@ARGV[0]") or die "$!";
  18. while(<f>){
  19.   chomp;
  20.   push @a, $_ if($_ eq "aaa");
  21.   print shift @a," $_" if($_ eq "bbb");
  22. }
  23. close(f);

  24. time perl jason680_m.pl testfile >/dev/null

  25. real    0m0.245s
  26. user    0m0.124s
  27. sys     0m0.092s


  28. time sed -nr -f mpstat.sed testfile >/dev/null  #sed的效率有点让人失望,不过不是code的问题,我觉得mpstat的code已经很犀利了,慢的原因应该是正则部分

  29. real    0m9.227s
  30. user    0m9.155s
  31. sys     0m0.046s

  32. time awk -f winway1988.awk testfile >/dev/null

  33. real    0m0.443s
  34. user    0m0.358s
  35. sys     0m0.031s

  36. cat ss.awk # 额的awk code,比perl还是慢,求效率更高的~
  37. /aaa/{if(t){i=t=j=0}a[i++]=$0}
  38. /bbb/{print $0,a[j++];t=1}

  39. time awk -f ss.awk testfile >/dev/null

  40. real    0m0.330s
  41. user    0m0.249s
复制代码

作者: winway1988    时间: 2012-04-08 14:23
回复 12# yinyuemi


    试试这个
  1. awk '/aaa/{a[++ntail]=$0}/bbb/{print a[++nhead],$0}'
复制代码

作者: yinyuemi    时间: 2012-04-08 14:27
回复 15# winway1988


    效率提高了~
  1. time awk -f winway1988_2.awk testfile >/dev/null

  2. real    0m0.341s
  3. user    0m0.265s
  4. sys     0m0.031s
复制代码

作者: ziyunfei    时间: 2012-04-08 15:31
awk '/aaa/{hash[++i]=$0}/bbb/{print hash[++j]"\t"$0}' file
作者: ziyunfei    时间: 2012-04-08 15:36
重复了
作者: dahaoshanhe    时间: 2012-04-08 15:40
回复 16# yinyuemi


这个帖子真霸道
作者: ziyunfei    时间: 2012-04-08 16:25
不管需要不需要 awk总会把$0切割成字段.这会耗费不少时间.就像perl用了-a.
作者: dragon23452345    时间: 2012-04-11 16:52
提示: 作者被禁止或删除 内容自动屏蔽
作者: jason680    时间: 2012-04-11 17:10
dragon23452345 发表于 2012-04-11 16:52
各位的代码都很精彩,不过感觉通用性不强,如果除了aaa,bbb,还有ccc,ddd配对就不行了


would you show the code for common, not just SAID it
作者: dragon23452345    时间: 2012-04-11 18:17
提示: 作者被禁止或删除 内容自动屏蔽




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2