如何提高 awk 的计算速度 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
deasty
V2EX    问与答

如何提高 awk 的计算速度

  •  
  •   deasty 2020-06-18 08:55:14 +08:00 via iPhone 4262 次点击
    这是一个创建于 2009 天前的主题,其中的信息可能已经有所发展或是发生改变。
    有一个 50M 的文本,90 多万行,每行有个数字,用 shell 写个脚本用 awk 取数后经过一个幂运算再输出到新文本,7 个小时过去了,才完成 20 多万行,如何能提高这个效率?
    第 1 条附言    2020-06-18 10:07:36 +08:00
    原始数据
    BJ|986|daxingqu
    GZ|959|tianhequ
    …省略 90 万行
    我的需求结果是把每行的数字乘以 1024 的平方后放在行首,结果如下
    1033895936|BJ|986|daxingqu
    1005584384|GZ|959|tianhequ
    …省略 90 万行
    第 2 条附言    2020-06-18 10:56:38 +08:00
    $./get.sh input.txt output.txt
    $more get.sh
    #!/bin/sh
    m =$(wc -l $1 |awk {'print $1'})
    for ((i = 1;i <=$m;i ++))
    do
    sed -n ${i}p $1 |awk -F "|" {'print $2*1024^2'} |tr "\n" "|">>$2&&sed -n ${i}p $1 >>$2
    done
    第 3 条附言    2020-06-18 11:18:10 +08:00
    哎,解决了,自己犯 2 了……
    26 条回复    2020-06-18 19:13:42 +08:00
    amoia50
        1
    amoia50  
       2020-06-18 08:58:21 +08:00 via iPhone
    python 不香吗[狗头]
    iintothewind
        2
    iintothewind  
       2020-06-18 09:05:47 +08:00
    xargs, parallel 都可以并行处理 可以试试
    rrfeng
        3
    rrfeng  
       2020-06-18 09:07:36 +08:00 via Android
    每行只有一个数字?没别的?
    运算具体是啥?

    你这相当于没说,咋分析
    delectate
        4
    delectate  
       2020-06-18 09:08:00 +08:00
    7 小时大约 25200s,处理 20w 行,一秒 10 行,不够快。
    要么 py+多进程,要么像楼上说的并行处理,或者干脆把文件拆分,然后多个一起跑也行。
    FrankHB
        5
    FrankHB  
       2020-06-18 09:14:10 +08:00
    为什么非要制造瓶颈?这种简单任务你用 C 临时糊个都不用几分钟,省下几个小时不香吗……
    lululau
       
    lululau  
       2020-06-18 09:15:01 +08:00 via iPhone
    单行命令的文本处理,python 真不香,sed awk perl ruby 不知道香到哪里去了,你也配叫脚本语言
    CEBBCAT
        7
    CEBBCAT  
       2020-06-18 09:25:54 +08:00 via Android
    上次可能是计算 int64 的移位,awk 确实没有 Python 快,我跑起来一会儿 awk 了发现还没跑好,然后再开了一个终端去写 Python,等我写完跑出结果了 awk 还是没有算完。

    楼上这么说有什么依据吗?
    momocraft
        8
    momocraft  
       2020-06-18 09:50:38 +08:00
    "经过一个幂运算" 是 awk 自己的计算吗?
    layorlayor
        9
    layorlayor  
       2020-06-18 09:51:39 +08:00
    把代码贴出来吧。感觉不应该这么慢
    lululau
        10
    lululau  
       2020-06-18 09:52:55 +08:00
    @CEBBCAT 举两个最简单也最常见的例子:

    文本替换:

    sed 's///'
    gawk 'gsub()'
    perl -pe 's///'
    ruby -pe 'gsub!()'

    取一列并做变换:

    gawk '{print $1*2}'
    perl -alne 'print $F[0]*2'
    ruby -ane 'puts $F[0].to_i * 2'

    欢迎楼下用 python 弄一个更简单的写法来打脸

    还忘了说最近看到的一个行列结构文本处理的瑞士军刀 miller
    ylrshui
        11
    ylrshui  
       2020-06-18 10:10:31 +08:00 via iPhone
    估计 excel 都比这快
    thedog
        12
    thedog  
       2020-06-18 10:30:38 +08:00
    awk 不应该那么慢吧,很多时候,这种简单任务,awk 比 python 快的。
    runze
        13
    runze  
       2020-06-18 10:37:07 +08:00
    代码贴出来看看? awk 虽然不算快,但绝不至于慢到这种程度
    TimePPT
        14
    TimePPT  
    PRO
       2020-06-18 10:41:56 +08:00 via Android
    这么规整的结构,还要做计算。pandas 很香的
    ygtq
        15
    ygtq  
       2020-06-18 10:45:51 +08:00
    show me the code :)
    xlcoder166
        16
    xlcoder166  
       2020-06-18 10:46:57 +08:00
    现有代码不变的思路 - 分治

    1. 拆原文件至 90W / n ( CPU 核心数)个文件
    2. shell 并行处理 拆分的文件
    youngster
        17
    youngster  
       2020-06-18 10:56:11 +08:00
    估计不是 awk 慢,是你运算太慢,换个换个运算快的语言应该都能解决
    layorlayor
        18
    layorlayor  
       2020-06-18 10:58:48 +08:00
    awk -F'|' '{print $2*1024*1024"|"$0}' 这个很快呀
    layorlayor
        19
    layorlayor  
       2020-06-18 11:03:22 +08:00   1
    awk -F'|' '{print $2*1024*1024"|"$0} input.txt > output.txt
    Vegetable
        20
    Vegetable  
       2020-06-18 11:05:14 +08:00
    你这脚本写的是个啥,处理单行文本还有 for 循环?看着就害怕
    Vegetable
        21
    Vegetable  
       2020-06-18 11:09:39 +08:00
    btw,1024*1024 就是 2**20
    klesh
        22
    klesh  
       2020-06-18 11:22:03 +08:00
    测试命令:
    seq 0 10000 | awk '{print "foo|"$1"|bar"}' > test.txt
    time awk -F'|' '{print $2*1024*1024"|"$0}' test.txt

    结果:
    10484711424|foo|9999|bar
    10485760000|foo|10000|bar

    ________________________________________________________
    Executed in 76.44 millis fish external
    usr time 54.70 millis 0.00 micros 54.70 millis
    sys time 21.51 millis 962.00 micros 20.54 millis


    硬件
    CPU: Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
    SSD: SanDisk SD8SB8U5
    Kelan
        23
    Kelan  
       2020-06-18 11:57:10 +08:00
    这么小的文本跑 7 个小时有点离谱了把。
    0x11901
        24
    0x11901  
       2020-06-18 16:53:02 +08:00
    说实话每次遇到这种问题总有一群人说用 python 不香么……

    真是应了那句老话:当你手上有一把锤子的时候,看所有的东西都是钉子
    freelancher
        25
    freelancher  
       2020-06-18 18:40:49 +08:00
    结果是个啥。得说呀。还是说附言二就解决了?
    Semidio
        26
    Semidio  
       2020-06-18 19:13:42 +08:00
    @freelancher #24 注意看 18L 和附言 2 的区别
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5214 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 104ms
    UTC 08:03 PVG 16:03 LAX 00:03 JFK 03:03
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86