сопоставление определенной подстроки с регулярными выражениями с использованием awk - PullRequest
3 голосов
/ 15 декабря 2010

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

Структура имени файла похожа на: "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

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

Спасибо.

Ответы [ 4 ]

2 голосов
/ 15 декабря 2010

Вы должны быть в состоянии использовать осмотры, и я не думаю, что 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
1 голос
/ 31 января 2012

Хотя решение grep действительно очень хорошо, OP не упоминал операционную систему, а опция -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}'
0 голосов
/ 31 января 2012

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

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
0 голосов
/ 15 декабря 2010

Трудность здесь заключается в том, что (.*) перед необязательным (-W.*)? сожирает последний текст.Использование не жадных совпадений также не помогает.Мой regex-fu, к сожалению, слишком слаб для этого-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.

...