grep 命令不搜索完整模式

grep 命令不搜索完整模式

我在 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请告诉我。

答案1

鉴于您对 Pascal 的回答的评论,您想要的事情是无法实现的。

您引用的字符串 ( SH?*???????????????US.*) 不是 grep rexexp。它看起来可能是 shell 样式的 glob,但在 grep 中,与单个字符匹配的元字符不是?,而是.*并不表示“任意数量的任意字符”。

如果我理解正确的话,你的问题可以归结为“我在数据库中存储了这个 glob 样式的正则表达式,我可以使用什么工具根据某些字符串对其进行评估“;在这种情况下,答案是”不是 grep;你必须找到或编写一个能够理解你已经关注的正则表达式的工具“。

参考自 gnu grep 手册页:

句点 . 匹配任意单个字符。

重复

   A regular expression may be followed by one of several repetition operators:
   ?      The preceding item is optional and matched at most once.
   *      The preceding item will be matched zero or more times.

答案2

使用 egrep 和适当的正则表达式,例如

"^SH[0-9._]*US\.csv\.gz.*$"

答案3

感谢戴维·W.在 stackoverflow 中问题,以下 perl 脚本会将您无用的 GLOB 转换为正则表达式,然后您可以在 grep 中使用它。将脚本保存到,glob2regex.pl然后您可以

grep `./glob2regex.pl SH?*???????????????US.*` 

glob2regex.pl:

#!/usr/bin/perl

my $GLOB = $ARGV[0];
print glob2regex($GLOB);
print "\n";

sub glob2regex {
my $glob = shift;

my $regex = undef;
my $previousAstrisk = undef;

foreach my $letter (split(//, $glob)) {
    #
    #    ####Check if previous letter was astrisk
    #
    if ($previousAstrisk) {
        if ($letter eq "*") { #Double astrisk
            $regex .= ".*";
            $previousAstrisk = undef;
            next;
        } else {        #Single astrisk: Write prev match
            $regex .= "[^/]*";
            $previousAstrisk = undef;
        }
    }
    #
    #   ####Quote all Regex characters w/ no meaning in glob
    #
    if ($letter =~ /[\{\}\.\+\(\)\[\]]/) {
        $regex .= "\\$letter";
        #
        #   ####Translate "?" to Regular expression equivelent
        #
    } elsif ($letter eq "?") {
        $regex .= ".";
        #
        #   ####Don't know how to handle astrisks until  the next line
        #
    } elsif ($letter eq "*") {
        $previousAstrisk = 1;
        #
        #   ####Convert backslashes to forward slashes
        #
    } elsif ($letter eq '\\') {
        $regex .= "/";
        #
        #   ####Just a letter
        #
    } else {
        $regex .= $letter;
    }
}
#
#   ####Handle if last letter was astrisk
#
if ($previousAstrisk) {
    $regex .= "[^/]*";
}
#
#    ####Globs are anchored to both beginning and ending
#
$regex = "^$regex\$";
return $regex;
}

相关内容