Назад | Перейти на главную страницу

Команда grep не выполняет поиск по всему шаблону

Я столкнулся с проблемой при использовании команды 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 пожалуйста, дай мне знать.

Учитывая ваш комментарий к ответу Паскаля, то, что вы хотите, невозможно сделать.

Цитируемая вами строка (SH?*???????????????US.*) не является grep rexexp. Похоже, это может быть глобус в стиле оболочки, но в grep метасимвол, который соответствует одному символу, не ?, его ., и * не означает «любое количество любого символа».

Итак, если я правильно понимаю, ваш вопрос сводится к следующему: "У меня есть это регулярное выражение в стиле глобуса, хранящееся в базе данных, какой инструмент я могу использовать, чтобы оценить его по некоторым строкам"; в этом случае ответ будет"не 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.

Используйте egrep и правильное регулярное выражение, например

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

Благодаря сценарию автора Дэвид В. в 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;
}