Linux 下遍历大文件每一行的最佳方法,最好是命令 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
vus520
V2EX    问与答

Linux 下遍历大文件每一行的最佳方法,最好是命令

  •  
  •   vus520 2015-12-05 10:46:00 +08:00 5786 次点击
    这是一个创建于 3598 天前的主题,其中的信息可能已经有所发展或是发生改变。
    via: http://liuzhiqiangruc.iteye.com/blog/1454797

    原始需求是想监控文件增加的每一行,传给外部程序处理。

    实际上的办法是定时遍历文件的每行,再传给外部程序处理。
    94 条回复    2015-12-06 21:49:48 +08:00
    angelface
        1
    angelface  
       2015-12-05 10:49:21 +08:00
    iNotify
    angelface
        2
    angelface  
       2015-12-05 10:50:06 +08:00
    RemRain
        3
    RemRain  
       2015-12-05 10:53:22 +08:00 via iPhone
    tail -f
    程序实现的话, 2.6.32 内核以上用 inotify ,也可以直接用 libev
    clino
        4
    clino  
       2015-12-05 11:00:42 +08:00
    tail -f +1
    xufang
        5
    xufang  
       2015-12-05 11:09:15 +08:00
    awk 比 perl 要快的,楼主你没用对。
    不信的话,楼主可以把你这个发到 ChinaUnix 的 Shell 板块,一堆人会给出更快的方案。

    不过我现在喜欢用 golang 来做这样的事情,因为楼主你注意到没有,这些脚本写得再高效,也只能单核运行,很难利用多核上。

    而 golang 的话,天然支持多核,用起来很方便。
    http://rodaine.com/2015/04/async-split-io-reader-in-golang

    用这种模式处理大文件话,立马层次就不一样了。
    xufang
        6
    xufang  
       2015-12-05 11:09:50 +08:00
    楼上给出 tail 的,明显是看帖不回帖的,楼主不用理他们。
    vus520
        7
    vus520  
    OP
       2015-12-05 11:12:26 +08:00
    @xufang go lang 大法好
    vus520
        8
    vus520  
    OP
       2015-12-05 11:14:25 +08:00
    @clino tail 可以从头开始遍历一个文件吗,没有找到参数
    xufang
        9
    xufang  
       2015-12-05 11:19:30 +08:00
    而且 golang 的正则引擎虽然残废不完备,但是比较快。秒杀了很多脚本语言。
    具体可以见 russ cox (golang 主要贡献者)的论文
    《 Regular Expression Matching Can Be Simple And Fast 》
    https://swtch.com/~rsc/regexp/regexp1.html

    这标题,啧啧,狠狠的打脸啊。
    skydiver
        10
    skydiver  
       2015-12-05 11:22:34 +08:00
    @vus520 可以。 tail -n +N 就是从头第 N 行开始,想从头开始直接 tail -f -n +1 就可以了
    skydiver
        11
    skydiver  
       2015-12-05 11:23:14 +08:00
    @xufang
    skydiver
        12
    skydiver  
       2015-12-05 11:25:10 +08:00
    @xufang 吹 Go 没关系,用不着靠贬低 tail 来说事儿,不觉得拿 Go 和 tail 比太 low 了么。
    另外不要养成没事儿扣帽子的习惯。
    xufang
        13
    xufang  
       2015-12-05 11:26:34 +08:00
    @skydiver tail 的楼主的原始需求,亲。楼主后来的需求是遍历大文件每一行哦。
    skydiver
        14
    skydiver  
       2015-12-05 11:28:08 +08:00
    @xufang 另外 lz 题目里写了最好是命令,回复 tail 怎么就成了回帖不看贴了
    哦,你说的看贴不回贴。我们这不是回帖了么,怎么叫不回贴了
    skydiver
        15
    skydiver  
       2015-12-05 11:29:08 +08:00
    @xufang 这个需求 tail 就可以满足,而且还满足 lz 说的最好是命令
    xufang
        16
    xufang  
       2015-12-05 11:29:09 +08:00
    @xufang 打快了就发出了。

    原始需求用 tail -f 没错,新需求和 tail 完全不搭嘎。
    awk/perl 适合,我鼓吹一下 golang 也挺适合。并不是那它和 tail 比啊。
    xufang
        17
    xufang  
       2015-12-05 11:30:57 +08:00
    @skydiver 这,如果是 tail -f -n +1 完全是赶鸭子上架,后面正则匹配和替换等等,完全不搞不定。
    skydiver
        18
    skydiver  
       2015-12-05 11:31:41 +08:00
    @xufang 你需要看看 lz 的原始需求。
    并没有什么新需求, lz 说了那只是实际上的办法。
    有好的办法解决原始需求,何必纠结这个实际方法。
    skydiver
        19
    skydiver  
       2015-12-05 11:32:47 +08:00
    @xufang 通过管道传给 awk sed perl 或者自己写的程序处理就可以了,这就是*nix 哲学
    xufang
        20
    xufang  
       2015-12-05 11:37:33 +08:00
    @skydiver 你看下楼主的帖子。那三个脚本
    xufang
        21
    xufang  
       2015-12-05 11:39:05 +08:00
    @skydiver 呃,你如果转进到 Unix 哲学,我只能推测你估计没有像我和楼主一样真实处理过大文件的文本。。。
    Andiry
        22
    Andiry  
       2015-12-05 11:48:38 +08:00
    500w+行,每行算 100bytes ,也就是 500MB ,也不算什么大文件,全部读进内存,然后开多线程用 seek 分段处理就完了
    skydiver
        23
    skydiver  
       2015-12-05 11:49:01 +08:00
    @xufang 这只是你的不合理推测。
    逐行处理不需要把文件全读到内存里,所以跟文件大小没有关系。
    vus520
        24
    vus520  
    OP
       2015-12-05 11:49:16 +08:00
    @xufang @skydiver 二位这么执着我真是又醉又感动

    现在的需求其实是找出每一行数据,交给其它进程数据,现在只是想知道,哪种方式最快最方便最省内存

    我依次测试过 cat 再 loop ,试过 awk ,现在的场景是处理 50G 以上的日志文件分析进行抽取。

    考虑到生产环境中并没有安装 go ,所以命令是优先的,方便集群中部署。

    我正在测试几个命令的效率,回头跟大家 update 下
    vus520
        25
    vus520  
    OP
       2015-12-05 11:51:04 +08:00
    @skydiver 是的,我的需求跟你说的是一致的。不管文件多大,我每次只处理一行,直接扔给外部程序处理,这里只关注遍历文件的速度,外部程序处理的速度暂时不关注
    xufang
        26
    xufang  
       2015-12-05 11:54:06 +08:00 via Android
    @Andiry golang 欢迎您。[微笑]
    xufang
        27
    xufang  
       2015-12-05 11:58:35 +08:00 via Android
    @skydiver 。。。 这,好吧,您继续坚持 tail 遍历文件吧。,我是说服不了啦。
    xufang
        28
    xufang  
       2015-12-05 12:07:42 +08:00
    @Andiry 补上 https://blog.klauspost.com/an-async-read-ahead-package-for-go/

    这套东东比手动撸 c++/java 舒服多了。至于脚本语言,有了 GIL 就别想啦。
    clino
        29
    clino  
       2015-12-05 12:16:54 +08:00
    @vus520 tail 可以从头开始遍历啊 -n 够大就可以从头开始
    xufang
        30
    xufang  
       2015-12-05 12:18:25 +08:00
    @clino 亲,也请再看下楼主原帖哦,楼主要的是一个高效的遍历文件每一行并且做正则替换的方法。。。
    ryd994
        31
    ryd994  
       2015-12-05 12:26:17 +08:00
    问题是为什么不用 tail -f 解决原始需求而是用这种绕路的方法解决一个人为的需求?

    对于新需求, BC 和 EF 之间是否有顺序关系, BC 是否一定在 EF 之前, EF 是否只出现一次?如果是: sed

    还有,如果你有多核的话,可以直接 seek 到 1/n 大小处,找到最近的换行,然后就可以并行化了。注意处理好边界问题。

    你现在的方法估计还有个瓶颈在 IO 上,因为修改的部分不大,但要复制一份的 IO 不小。直接写个 C 程序处理并不复杂,直接在当前位置写入,表面上看是随机写,但有缓存的情况下不需要担心。
    xufang
        32
    xufang  
       2015-12-05 12:28:53 +08:00 via Android
    @ryd994 楼主这需求其实是离线收集日志,估计还用上了 fabric ansible 这些工具。所以才会这样,你琢磨一下。
    ryd994
        33
    ryd994  
       2015-12-05 12:32:06 +08:00
    @xufang 那写个 C 的小程序是值得的, 反正只用到基本的文件读写方面的知识,写个真不难
    xufang
        34
    xufang  
       2015-12-05 12:33:39 +08:00 via Android
    嗯,不过我现在成了 go 粉了,在不遗余力地游说楼主呢。
    ryd994
        35
    ryd994  
       2015-12-05 12:33:48 +08:00
    这个任务,瓶颈是 IO ,有条件的话上 SSD 或者全部放内存
    ryd994
        36
    ryd994  
       2015-12-05 12:35:41 +08:00
    @xufang 文件读写这件事由硬件制约,并不是太适合高度并行化,用 Go 未必合适。
    clino
        37
    clino  
       2015-12-05 13:15:20 +08:00
    @xufang 这有什么问题吗? 如果要做正则替换就做啊.
    xufang
        38
    xufang  
       2015-12-05 13:16:22 +08:00
    @ryd994 楼主还要正则替换呢
    具体请看我 28 楼回复的文章,很详细了。
    xufang
        39
    xufang  
       2015-12-05 13:17:31 +08:00
    @clino 楼主要的高效哦,在他的原帖拒绝了管道的方案。
    clino
        40
    clino  
       2015-12-05 13:27:59 +08:00
    @xufang 要的是高效 管道不一定会低效 原帖低效的原因是每一行都重新调用一个新进程,如果用同样一个进程效率不会这么低
    xufang
        41
    xufang  
       2015-12-05 13:29:13 +08:00
    @clino 请看完原帖啊,所以楼主那他的 perl/awk 的改进版来挑战呀,我用 golang 排了一下。
    clino
        42
    clino  
       2015-12-05 13:48:54 +08:00
    @xufang 没看到你的结果啊 要楼主实际比较过才行吧
    另外我看了一下上面楼主根本不想用 go 啊...
    xufang
        43
    xufang  
       2015-12-05 13:51:29 +08:00
    @clino https://github.com/klauspost/readahead 饭这个不能让人喂的啊。

    呵呵,单核性能够用就行,但是纯讨论了话,当然是精益求精了。
    xufang
        44
    xufang  
       2015-12-05 13:52:32 +08:00
    @clino 另外,不要做伸手党哦。
    clino
        45
    clino  
       2015-12-05 13:59:09 +08:00
    @xufang 有点莫名其妙 什么伸手党
    我没有要吃饭 你硬塞给我个 go 的玩意说是喂饭 然后说我伸手党 是有什么问题? 难道是 go 教里的原教旨主义?

    我是说楼主一样的原始文件那两种方法都有测试时间结果 那要有 go 的方法对比测试一下时间才是实际
    xufang
        46
    xufang  
       2015-12-05 14:01:52 +08:00
    @clino 呵呵,转进的真好。
    xufang
        47
    xufang  
       2015-12-05 14:04:14 +08:00
    诸位觉得我的理论无懈可击了,所以逼我 show 代码了吗?

    老实说,这块代码我也是花了一些心思写的,觉得是业内前沿的技术。不愿意白给的哦。

    反正思路我也指出了,看客们自己判断。
    kotokz
        48
    kotokz  
       2015-12-05 14:17:19 +08:00
    这种我肯定会用 nim +mmap
    pright
        49
    pright  
       2015-12-05 15:58:55 +08:00
    #一粉顶十黑的绝佳例子#
    xufang
        50
    xufang  
       2015-12-05 16:03:26 +08:00 via iPhone
    @pright 辩不过就加 tag ,这样的 V2EX 人才越来越兴旺了。
    xufang
        51
    xufang  
       2015-12-05 16:07:48 +08:00
    在重复一下我在 /t/240708 的观点,以目前小学生泛滥的情况,我真的不愿意下场撕了。

    夏虫不可语冰,年纪轻轻就学会了拒绝新事物新技术的,真是够了。
    5thcat
        52
    5thcat  
       2015-12-05 16:53:27 +08:00
    顺序读文件还要并行真是醉了, 真是给 golang 抹黑
    undeflife
        53
    undeflife  
       2015-12-05 16:55:20 +08:00   1
    楼上这位还真是 手里拿着锤子,看什么都像是钉子 ...

    golang 没什么,golang 教徒就很让人烦了
    xufang
        54
    xufang  
       2015-12-05 16:55:46 +08:00
    @5thcat 切,正则处理不耗 CPU ?这位新来的,有一个回帖不看贴的。
    xufang
        55
    xufang  
       2015-12-05 16:56:18 +08:00
    @undeflife 嗯嗯,帽子发得很溜,在我看来你比你楼上还要 LOW
    5thcat
        56
    5thcat  
       2015-12-05 16:57:09 +08:00
    @xufang 就问一句:多核能加速顺序文件读吗?
    xufang
        57
    xufang  
       2015-12-05 16:57:21 +08:00
    来来来,让我看下 V2EX 今天又多少小学生在线。 :)
    xufang
        58
    xufang  
       2015-12-05 16:58:16 +08:00
    @5thcat 呵呵,不用并行,你能在等 IO 的时候,把 CPU 也用上吗?
    xufang
        59
    xufang  
       2015-12-05 16:59:41 +08:00
    诸位小学生,回帖先看贴,我在前讲过 N 次我的观点了,不要略过。
    xufang
        60
    xufang  
       2015-12-05 17:22:12 +08:00
    舌战了一下午,除了这幅图,没有其他可以表达我此刻的感受了。

    looyao
        61
    looyao  
       2015-12-05 18:25:15 +08:00
    这里可以粘帖代码么,额
    //tail_demo.c

    #include <stdio.h>
    #include <strings.h>
    #include <stdlib.h>
    #include <unistd.h>

    #include <sys/inotify.h>


    int tail(char *path, long *pos);

    int main(int argc, char *argv[])
    {
    int inotify_fd, watch_fd, n;
    long pos;
    struct inotify_event event;
    void *evp;
    char *path;

    if (argc != 2) {
    return -1;
    }

    path = argv[1];
    pos = 0;

    if (tail(path, &pos) < 0) {
    return -2;
    }

    evp = &event;

    inotify_fd = inotify_init();
    watch_fd = inotify_add_watch(inotify_fd, path, IN_MODIFY | IN_DELETE_SELF | IN_MOVE_SELF);
    if (watch_fd <= 0) {
    fprintf(stderr, "inotify_add_watch error:%s\n", path);
    return -3;
    }

    //这里可以使用 select, poll 轮询下 inotify_fd

    while (1) {
    bzero(&event, sizeof(struct inotify_event));
    n = read(inotify_fd, evp, sizeof(struct inotify_event));
    if (n <= 0) {
    fprintf(stderr, "read error\n");
    break;
    }

    if (event.mask & IN_MODIFY) {
    tail(path, &pos);
    }
    }

    }

    int tail(char *path, long *pos)
    {
    FILE *handle;
    char buf[1024];

    handle = fopen(path, "r");
    if (!handle) {
    fprintf(stderr, "can't open file:%s\n", path);
    return -1;
    }

    fseek(handle, *pos, SEEK_SET);

    while (!feof(handle)) {
    bzero(buf, sizeof(buf));
    fgets(buf, sizeof(buf), handle);
    printf("%s", buf);
    *pos = ftell(handle);
    }

    fclose(handle);
    }


    编译:
    gcc tail_demo.c -o tail_demo
    使用:
    ./tail_demo 文件路径
    xufang
        62
    xufang  
       2015-12-05 18:39:20 +08:00
    牛哄哄喷我的小学生呢,不要停啊。继续喷,来拓展我的世界观。
    vus520
        63
    vus520  
    OP
       2015-12-05 18:52:16 +08:00
    @looyao

    我编译了一下, mac 上找不到 sys/inotify.h

    不过却找到了这个东西
    https://github.com/facebook/watchman
    looyao
        64
    looyao  
       2015-12-05 18:58:15 +08:00
    @vus520 不好意思, Linux 才可以,没有说明。代码临时写的,可能不够严谨,其实就是这个意思,默认读取文件,全部读取完成后监控文件改变再读,这样。不用怕大文件,其实没什么关系。 PS :代码粘上来米有缩进,好丑,下次不粘了,哈哈。
    neoblackcap
        65
    neoblackcap  
       2015-12-05 18:59:17 +08:00
    @vus520 inotify 是 linux 内核特性, Mac 自然没有。
    aku
        66
    aku  
       2015-12-05 19:33:07 +08:00 via Android
    @xufang 不愿意 show code 的话, release binary 就可以了

    go 的好处这时候就体现出来了
    clino
        67
    clino  
       2015-12-05 19:37:34 +08:00
    @neoblackcap 为什么 tail 不需要用到 inotify 就可以监控文件改变呢
    xufang
        68
    xufang  
       2015-12-05 19:38:00 +08:00
    @aku 偏不,我也生气了,就一起口炮下去。
    xufang
        69
    xufang  
       2015-12-05 19:39:50 +08:00
    @clino 简单的很, 在文件尾 while(1) {read(n); sleep(m)} 就可以了, 你试下就知道
    xufang
        70
    xufang  
       2015-12-05 19:41:59 +08:00
    @clino 一个小技巧就是 read(n) 每每读不到数据的时候,以斐波那契数列的时间来 sleep ,当然这个技巧有无效果就见仁见智了。 10 年前,国外的邮件列表就对这个讨论得很充分了。
    skydiver
        71
    skydiver  
       2015-12-05 19:44:45 +08:00
    @clino tail 用的就是 inotify
    xufang
        72
    xufang  
       2015-12-05 19:49:29 +08:00
    skydiver
        73
    skydiver  
       2015-12-05 19:53:49 +08:00
    @xufang 我说的 gnu 的 coreutils ,你拿个 busybox 出来做甚
    xufang
        74
    xufang  
       2015-12-05 19:56:53 +08:00
    @skydiver 呵呵,转进的好。
    skydiver
        75
    skydiver  
       2015-12-05 20:02:51 +08:00
    @xufang 呵呵。 block 不送。
    xufang
        76
    xufang  
       2015-12-05 20:04:25 +08:00
    终于有人使出 block 大法了,我还以为小学生们会比较好面子的死撑的呢。
    clino
        77
    clino  
       2015-12-05 20:28:42 +08:00
    @skydiver 我搜了一下应该两种方法都有支持,优先 inotify 不行就用 polling 的方式
    skydiver
        78
    skydiver  
       2015-12-05 20:31:20 +08:00
    @clino 是的 我记得用不了 inotify 的时候会有提示 使用 polling
    xufang
        79
    xufang  
       2015-12-05 20:34:40 +08:00 via Android
    一个简单的事实: tail 的历史比 inotify 要老,所以小学生哪来的如此的自信满满?
    wjchen
        80
    wjchen  
       2015-12-05 20:52:19 +08:00
    可以 hook 写文件的 api 。
    msg7086
        81
    msg7086  
       2015-12-06 07:33:36 +08:00
    好好的 V2EX 搞得乌烟瘴气,能不能消停下?
    xufang
        82
    xufang  
       2015-12-06 08:50:14 +08:00 via Android
    @msg7086 一开始我回帖是很平和的哦

    结果小学生学艺不精不自量力喷我反被喷

    怪我咯?
    RemRain
        83
    RemRain  
       2015-12-06 12:22:57 +08:00
    @xufang
    LZ 的需求是: 1. 监控文件增加的每一行; 2. 简单的字符串替换; 3. 最好是命令行

    需求里面监控文件增加才是难点,字符串替换怎么来都不是问题,所以楼下的建议都是 tail -f 作监控,管道来处理字符串替换,你这假装很有经验,不给出有帮助的回答并强行与所有人撕逼是为哪般?


    另外你答的几个看起来很厉害,实际没任何用的技术点,我可以给你分析下:

    1. awk 比 Perl 快, LZ 没用对, ChinaUnix 上很多人可以给出更快的方案

    事实上在文本简单处理上,各语言在效率上没有太大差异,处理速度完全取决于 IO 操作。 Linux 是有文件缓存的, LZ 之所以发现 Perl 比 awk 快,很有可能是 awk 后文件被缓存了一部分,之后 Perl IO 操作变快了。不看脚本内容,直接断言 LZ 没用对,而且不说哪里不对,说明你压根没意识到文件缓存的问题,或者说不知道有这个东西。

    2. 脚本写得再高效,只能单核运行,应该用 golang , golang 天然支持多核

    我以为 LZ 需求的效率取决于 IO 性能是有目共睹的,多核处理并不能加快 IO 处理速度,@5thcat 已经说明了。你回复说`你能在等 IO 的时候,把 CPU 也用上吗?` 我反问你一句,你把 CPU 都用上了,就不用等 IO 吗?

    3. golang 的正则引擎秒杀很多脚本语言,打了很多语言的脸

    那又如何? LZ 关心的是遍历,标题说明了,回复中也强调了。正则引擎快有啥用?另外真计较性能的话,你不觉得应该用普通的字符串查找、替换函数吗?锤子是好使,可这是螺丝啊
    xufang
        84
    xufang  
       2015-12-06 12:25:41 +08:00
    @RemRain 有一个看贴不回帖了,我的反复讲过,并行的好处就可把正则运算这部分工作摊到等 IO 时间做。

    懂了吗?
    xufang
        85
    xufang  
       2015-12-06 12:26:36 +08:00
    我敢打赌,你们这些乱喷的小学生根本没看我贴的两篇的文章。
    RemRain
        86
    RemRain  
       2015-12-06 12:32:48 +08:00
    @xufang 什么叫看贴不回帖?为何要用正则运算?你承认不知道文件缓存了?
    xufang
        87
    xufang  
       2015-12-06 12:34:29 +08:00
    @RemRain 为什么要用正则运算?自己去看楼主的原贴。

    在我看来你才不知道呢,你千万别又 low 到这种程度。
    xufang
        88
    xufang  
       2015-12-06 12:35:59 +08:00
    只会爬楼,不看各楼引用的帖子,真是够了。我下午还要出去玩,有什么干货赶紧说。
    RemRain
        89
    RemRain  
       2015-12-06 12:43:15 +08:00
    @xufang 可字符串查找、替换之类的函数更简单更快啊。另外,还是请教下,什么叫看贴不回帖?
    xufang
        90
    xufang  
       2015-12-06 12:45:23 +08:00
    @RemRain 所以你这个说法我们反对啊。不过即使查找替换也是 CPU 操作不是。

    但是一般业务用正则更普遍,所以我就安利了 golang 的正则引擎。

    刚才打快了,是回帖不看贴哦。
    xufang
        91
    xufang  
       2015-12-06 12:45:49 +08:00
    s/我们反对 /我没反对 /
    xufang
        92
    xufang  
       2015-12-06 13:02:23 +08:00
    出门了,最后我甩个半干货出来。

    并行处理存在理论上的优势,但是实现的时候要考虑 locality 的问题, golang 还有 gc 方面需要针对性优化。

    总之,知易行难。写代码其实是个技术活。
    xufang
        93
    xufang  
       2015-12-06 21:48:35 +08:00
    周末在这贴帖子我关注了两天,最终还是没有人提到 parallel 命令,这个让我进一步确认了在 V2EX 的技术自信
    https://en.wikipedia.org/wiki/GNU_parallel

    parallel 命令的思想和我说的这个初衷类似,不过有两点毛病
    1. 需要处理的数据行要上下文无关。
    2. 最要命的是 locality 不行,进程间通信比 golang 实现的原子操作慢多了。

    不过,在 CPU 操作很密集的情况下,不愿意自己撸代码的,可以考虑用它。
    xufang
        94
    xufang  
       2015-12-06 21:49:48 +08:00
    最后送本楼乱喷我的小学生们一句话,除了对新技术保持谦虚之外,回帖要看贴。

    以上。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2648 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 02:20 PVG 10:20 LAX 19:20 JFK 22:20
    Do have faith in what you're doing.
    ubao 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