2010-12-15 3 views
3

Я имею дело с определенными именами файлов и вам нужно извлечь информацию из них., соответствующий определенной подстроке с регулярными выражениями с использованием awk

Структура файла аналогична: «20100613_M4_28007834.005_F_RANDOMSTR.raw.gz»

с RANDOMSTR строка из 22 символов максимум, и которые могут содержать подстроку (или нет) с форматом «- W [0-9]. [0-9] {2}. [0-9] {3}». Эта подстрока также имеет уникальную особенность при запуске с «-W».

Информация, которую мне нужно извлечь, это подстрока RANDOMSTR без этой дополнительной подстроки.

Я хочу реализовать это в сценарии bash, и до сих пор лучшим вариантом, который я нашел, является использование gawk с регулярным выражением. Моя лучшая попытка до сих пор не удается:

gawk --re-interval '{match ($0,"([0-9]{8})_(M[0-9])_([0-9]{8}\\.[0-9]{3})_(.)_(.*)(-W.*)?.raw.gz",arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz" 
OTHER-STRING-W0.40+045 

Ожидаемые результаты:

gawk --re-interval '{match ($0,$regexp,arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_SOME-STRING.raw.gz" 
SOME-STRING 
gawk --re-interval '{match ($0,$regexp,arr); print arr[5]}' <<< "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz" 
OTHER-STRING 

Как я могу получить желаемый эффект.

Спасибо.

+0

Вы упомянули, что подстрока имеет образец `" -W [0-9]. [0-9] {2}. [0-9] {3} "` еще ваш пример ввода содержит `... W0.40 + 045.raw.gz`. Вам нужно угодить обоим? – 2010-12-15 14:37:16

+0

Я не включаю «.raw.gz» в качестве части подстроки. – RogerFC 2010-12-15 14:54:12

+0

Извините, я хотел обратить внимание на знак плюса, который не был бы покрыт вашим шаблоном. – 2010-12-15 15:01:14

ответ

2

Вы должны быть в состоянии использовать внешний вид, и я не думаю, что awk/gawk поддерживает это, но grep -P делает.

$ pat='(?<=[0-9]{8}_M[0-9]_[0-9]{8}\.[0-9]{3}_._)(.*?)(?=(-W.*)?\.raw\.gz)' 
$ echo "20100613_M4_28007834.005_F_SOME-STRING.raw.gz" | grep -Po "$pat" 
SOME-STRING 
$ echo "20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz" | grep -Po "$pat" 
OTHER-STRING 
0

Трудность здесь заключается в том, что (.*) перед опциональным (-W.*)? копирует последний текст. Использование не-жадного матча тоже не помогает. К сожалению, мое regex-fu слишком слабо для борьбы с этим.

Если вы не возражаете против многопроходного решения, то более простой подход состоял бы в том, чтобы сначала очистить вход, удалив конечный .raw.gz и возможный -W*.

str="20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz" 
echo ${str%.raw.gz} | # remove trailing .raw.gz 
    sed 's/-W.*$//' | # remove trainling -W.*, if any 
    sed -nr 's/[0-9]{8}_M[0-9]_[0-9]{8}\.[0-9]{3}_._(.*)/\1/p' 

Я использовал sed, но вы можете просто использовать gawk/awk.

0

не был в состоянии получить неохотно кванторы собирается, но проходит через два регулярных выражений в последовательности делает работу:

sed -E -e 's/^.{27}(.*).raw.gz$/\1/' << FOO | sed -E -e 's/-W[0-9.]+\+[0-9.]+$//' 
20100613_M4_28007834.005_F_SOME-STRING.raw.gz 
20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz 
FOO 
1

Хотя решение Grep это действительно очень приятно, что ОП не говоря уже о операционная система, а опция -P доступна только в Linux. Это также довольно просто сделать в awk.

$ awk -F_ '{sub(/(-W[0-9].[0-9]+.[0-9]+)?\.raw\.gz$/,"",$NF); print $NF}' <<EOT 
> 20100613_M4_28007834.005_F_SOME-STRING.raw.gz 
> 20100613_M4_28007834.005_F_OTHER-STRING-W0.40+045.raw.gz 
> EOT 
SOME-STRING 
OTHER-STRING 
$ 

Обратите внимание, что это нарушает на "20100613_M4_28007834.005_F_OTHER-STRING-W0_40 + 045.raw.gz". Если это риск, и -W показывает только в месте, указанном выше, было бы лучше использовать что-то вроде:

$ awk -F_ '{sub(/(-W[0-9.+]+)?\.raw\.gz$/,"",$NF); print $NF}'