【问题标题】:grep command is not search the complete patterngrep 命令不搜索完整模式
【发布时间】:2013-06-25 07:52:54
【问题描述】:

我在 shell 脚本中使用 grep 命令时遇到问题。实际上我有一个文件(PCF_STARHUB_20130625_1),其中包含以下记录。

SH_5.55916.00.00.100029_20130601_0001_NUC.csv.gz|438|3556691115
SH_5.55916.00.00.100029_20130601_0001_Summary.csv.gz|275|3919504621
SH_5.55916.00.00.100029_20130601_0001_UI.csv.gz|226|593316831
SH_5.55916.00.00.100029_20130601_0001_US.csv.gz|349|1700116234
SH_5.55916.00.00.100038_20130601_0001_NUC.csv.gz|368|3553014997
SH_5.55916.00.00.100038_20130601_0001_Summary.csv.gz|276|2625719449
SH_5.55916.00.00.100038_20130601_0001_UI.csv.gz|226|3825232121
SH_5.55916.00.00.100038_20130601_0001_US.csv.gz|199|2099616349
SH_5.75470.00.00.100015_20130601_0001_NUC.csv.gz|425|1627227450

我有一个存储在一个变量 (INPUT_FILE_T) 中的模式,并且想要从文件 (PCF_STARHUB_20130625_1) 中搜索模式。为此,我使用了以下命令

INPUT_FILE_T="SH?*???????????????US.*"
grep ${INPUT_FILE_T} PCF_STARHUB_20130625_1 

上述命令的输出如下

PCF_STARHUB_20130625_1:SH_5.55916.00.00.100029_20130601_0001_US.csv.gz|349|1700116234

我在输出中有两个问题,第一个是,输出中只显示一个条目(它应该包含两个条目),第二个问题是,输出包含不应该出现的“PCF_STARHUB_20130625_1:”。输出应如下所示

SH_5.55916.00.00.100029_20130601_0001_US.csv.gz|349|1700116234
SH_5.55916.00.00.100038_20130601_0001_US.csv.gz|199|2099616349

除了grep还有什么技巧请告诉我。

请帮助我解决这个问题。

【问题讨论】:

    标签: shell


    【解决方案1】:

    已将您的数据复制到我的input.txt

    $> (export INPUT_FILE_T="SH.*US\.*"; grep -h ${INPUT_FILE_T} input.txt)
    SH_5.55916.00.00.100029_20130601_0001_US.csv.gz|349|1700116234
    SH_5.55916.00.00.100038_20130601_0001_US.csv.gz|199|2099616349
    

    编辑

    如果您绝对必须使用 glob 模式,可能有一个实用程序可以做到这一点,但我不知道。以下快速 C 程序将有所帮助:

    #include <fnmatch.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAX_LINE_LENGTH 4096
    
    int main(int argc, char**argv)
    {
        if (argc < 2) { return EXIT_FAILURE; }
    
        FILE *in = stdin;
        const char *pattern = argv[1];
    
        char line[MAX_LINE_LENGTH + 1];
        while (fgets(line, MAX_LINE_LENGTH, in))
        {
            if (!fnmatch(pattern, line, 0))
            {
                printf("%s", line);
            }
        }
        return EXIT_SUCCESS;
    }
    

    编译(上面的程序在文件myfnmatch.c中):

    $> gcc -Wall myfnmatch.c -o myfnmatch
    

    使用示例(注意stdin重定向到input.txt):

    (export INPUT_FILE_T="SH?*???????????????US.*"; ./myfnmatch ${INPUT_FILE_T} <./input.txt)
    SH_5.55916.00.00.100029_20130601_0001_US.csv.gz|349|1700116234
    SH_5.55916.00.00.100038_20130601_0001_US.csv.gz|199|2099616349
    

    【讨论】:

    • 感谢rectummelancolique 的回复...但我无法更改搜索模式(不能使用SH.*US\.* 而不是SH?*???????????????US.*),因为它已经在数据库中提供。跨度>
    • 在 grep 正则表达式中 ? 并不意味着“任何东西”(至少根据我的 man grep)它意味着 The preceding item is optional and matched at most once。看来您的模式是 glob 模式而不是正则表达式。所以你必须改变它才能使用 grep。
    • 如果?在 grep 表达式中没有任何意义,那么为什么它正在搜索一种模式,它不会搜索任何模式..
    • 我只是在告诉你,就像我的男人一样。您没有告诉我们您正在使用哪个 shell,无论您的 grep 是 GNU grep 还是您的 shell 的内置,您也没有向我们提供完整的脚本。使用您的确切模式不会为我返回一个匹配项。所以我不知道你在说什么。
    • 那么您需要将您的模式更改为正则表达式。我不知道为什么您的 grep 将文件中的任何内容与您的 glob 模式匹配。它不应该。 grep --version 说什么?
    【解决方案2】:

    您可以使用.* 匹配任意字符任意次数,因此可以简化您的搜索模式(也不需要最后一个通配符):

    INPUT_FILE_T="SH.*US\."
    

    要从输出中删除文件名,请在 grep 中使用 -h 标志:

    $ grep -h ${INPUT_FILE_T} PCF_STARHUB_20130625_1
    SH_5.55916.00.00.100029_20130601_0001_US.csv.gz|349|1700116234
    SH_5.55916.00.00.100038_20130601_0001_US.csv.gz|199|2099616349
    

    【讨论】:

    • 感谢 Yossarian 的回复...但我无法更改搜索模式(不能使用 SH.*US\.* 代替 SH?*??????? ?????????US.*),因为它已经在数据库中提供。
    • 但问题仍然存在,grep 无法找到第二个模式。
    猜你喜欢
    • 1970-01-01
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多