美文网首页
grep命令保留第一行(C语言实现)

grep命令保留第一行(C语言实现)

作者: moriv4 | 来源:发表于2019-07-23 20:36 被阅读0次

    Linux中的 grep 是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。特别是在搜索日志、配置文件、过滤时应用非常广泛。

    然而这个命令有个美中不足的地方。它和其他命令配合使用时,把第一行的描述信息给过滤掉了。有时我们想要同时输出的第一行和匹配行。因为第一行的描述信息有助于我们理解后面每个字段的含义。

    比如我们查看和sda有关的文件系统

    $ df -h | grep sda  
    /dev/sda4       116G   58G   53G  53% /
    /dev/sda3       117G   63G   49G  57% /data
    /dev/sda1       646M   52M  595M   9% /boot/efi
    

    这里的116G 58G 53G 分别表示什么? 哪个才是剩余空间?
    我们希望得到结果是:

    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sda4       116G   58G   53G  53% /
    /dev/sda3       117G   63G   49G  57% /data
    /dev/sda1       646M   52M  595M   9% /boot/efi
    

    解决方案

    Stackoverflow给出的几种方案,grep 配合 sed 和 awk 使用。但我觉得这些方法不够好,于是我用C语言写了一个程序 grep1 。它可以智能判断标题行,输出彩色标题后调用 grep 完成匹配搜索。因为是调用 grep 的,所以 grep 能用的参数这里也可以用。

    为什么要强调智能判断标题行呢? 不是所有标题都在第一行,有的命令(netstat)标题在第二行。。。。。

    下面给出源码(少于60行),编译后移动到 /usr/local/bin/grep1 ,PATH环境变量一般包含 /usr/local/bin

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int is_title(char *s)
    {
        for (int i = 0; i < strlen(s) - 2; ++i)
        {
            if (s[i] == s[i+1] && s[i] == s[i+2])
                return 1;
        }
        return 0;
    }
    
    int main(int argc, char const *argv[])
    {
        /* compose command */
        char command[500] = "grep --color=always --exclude-dir={.bzr,CVS,.git,.hg,.svn} ";
        char sep[] = " ";
        for (int i = 1; argv[i] != NULL; ++i)
        {
            strcat(command, sep);
            strcat(command, argv[i]);
        }
        /* find title line */
        char buffer[500];
        char flows[3000] = {0};
        while (fgets(buffer, sizeof(buffer), stdin) != NULL)
        {
            if (is_title(buffer))
            {
                /* use green color to highlight title */
                printf("\033[;32m");
                printf("%s", buffer);
                printf("\033[0m");
                break;
            }
            /* save read string */
            strncat(flows, buffer, (size_t)(3000 - strlen(flows)));
        }
        fflush(stdout);
        /* call grep */
        FILE *fp;
        int c;
        char *flow_point = flows;
        fp = popen(command, "w");
        if (fp != NULL)
        {
            while ((c = *flow_point++) != 0)
                putc(c, fp);
            while ((c = getchar()) != EOF)
                putc(c, fp);
            putc(EOF, fp);
            pclose(fp);
        }
        return 0;
    }
    

    效果对比:


    深度截图_选择区域_20190723203432.png 深度截图_选择区域_20190723203251.png

    https://stackoverflow.com/questions/9969414/always-include-first-line-in-grep

    相关文章

      网友评论

          本文标题:grep命令保留第一行(C语言实现)

          本文链接:https://www.haomeiwen.com/subject/cpxzlctx.html