-1

I am facing a problem while using the grep command in shell script. Actually, I have one file (PCF_STARHUB_20130625_1) which contains below records.

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

And I have a pattern which is stored in one variable (INPUT_FILE_T), and I want to search the pattern from the file (PCF_STARHUB_20130625_1). For that I have used below command

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

The output of above command is coming as below

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

I have two problems in the output, first is, only one entry is shown in output (It should contain two entries) and second problem is, output contains "PCF_STARHUB_20130625_1:" which should not be came. Expected output should come like below

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

Is there any technique except grep please let me know.

3
  • 2
    SH?*??????US.* is a retarded regular expression, the solution is to change it.
    – Sirch
    Jun 25, 2013 at 10:33
  • Forget it, and can't delete it.
    – ott--
    Jun 25, 2013 at 12:59
  • What, after I put a script together for you to let you use GLOBs in grep? :p
    – Sirch
    Jun 25, 2013 at 13:04

3 Answers 3

4

Given your comment on Pascal's answer, what you want can't be done.

The string you quote (SH?*???????????????US.*) isn't a grep rexexp. It looks like it might be a shell-style glob, but in grep, the metacharacter that matches a single character isn't ?, it's ., and * doesn't mean "any number of any character".

So if I understand correctly, your question boils down to "I have this glob-style regular expression stored in a database, what tool can I use to evaluate it against some strings"; in that case, the answer is "not grep; you'll have to find - or write - a tool that understands the kind of regular expressions you've already fixated on".

References from the gnu grep man page:

The period . matches any single character.

and

Repetition

   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.
1

Use egrep and a propper regular expression like

"^SH[0-9._]*US\.csv\.gz.*$"
1
  • Thanks Pascal for your response... but I can't the change the searching pattern (can't use SH.*US\.* instead of SH?*???????????????US.*) as it is already feed on database. If any other technique(except grep) can be applied then please let me know
    – Sumit Vedi
    Jun 25, 2013 at 10:13
1

Thanks to a script by David W. in a stackoverflow question, the following perl script will convert your useless GLOB into a regex, which you can then use in grep. Save the script to glob2regex.pl and then you can

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;
}

Not the answer you're looking for? Browse other questions tagged .