Получить определенный шаблон из строки, используя Bash - PullRequest
0 голосов
/ 20 декабря 2011

Это может быть расширение вопроса: Включить переменные в строку кода bash

Я просто понимаю, что в моем тексте строки на самом деле имеют переменный формат.

2   118610455   P2_PM_2_5034    T   <DUP:TANDEM>    40  .   END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP 

1   859214  P2_M_061510_1_73    C   <DEL>   .   .   CIEND=-130,50;CIPOS=-57,93;END=860180;IMPRECISE;SVLEN=-966;SVTYPE=DEL;VALIDATED;DBVARID=esv10036;VALMETHOD=CGH;SVMETHOD=RD,RP

Мне нужно

2 118610455 118610566
1 859214 860180

Как показано выше, этот "END=#" может находиться в разных позициях в 8-м столбце.Поэтому в основном мне нужно найти часть «END = ..» из 8-го столбца, а затем набрать номер.Так что на самом деле речь идет о том, как извлечь конкретный шаблон из строки (в данном случае это «END =»)

Но как я могу это сделать?ТНХ

Ответы [ 3 ]

1 голос
/ 20 декабря 2011

Grep:

Вы можете использовать -o параметр grep для поиска:

Тест:

[jaypal:~/Temp] grep -o "END=[0-9]\+;" file | tr -ds 'END=|;' ''
118610566
860180

Но если вы ищете полное решение, то как насчет использования awk (извините, я знаю, что это не ваше требование. Но вот два решения:

Awk:

Если первый и второй параметры, которые вы хотите, не меняются по положению, то мы можем разделить каждое значение в определенных полях и затем выполнить цикл по каждому из них. Как только мы достигаем поля END, мы печатаем $ 1 и $ 4, а затем печатаем столбец рядом с END.

awk -v FS="[ ;=]" '{for(i=1;i<=NF;i++) if ($i=="END") print $1,$4,$(i+1)}' file

Тест:

[jaypal:~/Temp] cat file
2   118610455   P2_PM_2_5034    T   <DUP:TANDEM>    40  .   END=118610566;SVLEN=110;SVTYPE=TDUP;CIPOS=-100,55;CIEND=-56,100;IMPRECISE;DBVARID=esv7540;VALIDATED;VALMETHOD=CGH;SVMETHOD=RP 
1   859214  P2_M_061510_1_73    C   <DEL>   .   .   CIEND=-130,50;CIPOS=-57,93;END=860180;IMPRECISE;SVLEN=-966;SVTYPE=DEL;VALIDATED;DBVARID=esv10036;VALMETHOD=CGH;SVMETHOD=RD,RP

[jaypal:~/Temp] awk -v FS="[ ;=]" '{for(i=1;i<=NF;i++) if ($i=="END") print $1,$4,$(i+1)}' file
2 118610455 118610566
1 859214 860180

GNU AWK:

Если у вас есть gawk, то у него есть встроенная функция под названием gensub. Это поддерживает обратные ссылки. Таким образом, вы также можете сделать следующее -

gawk '{print $1,$2,gensub(/.*\<END\>=(.[^;]*);.*/,"\\1",$0)}' file

Тест:

[jaypal:~/Temp] gawk '{print $1,$2,gensub(/.*\<END\>=(.[^;]*);.*/,"\\1",$0)}' file
2 118610455 118610566
1 859214 860180
0 голосов
/ 20 декабря 2011

Вы можете использовать для этого скрипт на Perl, например:

pax> perl -ne '{
         @arr=split;
         if (@arr[7] =~ /^END=/) {
             @arr[7] =~ s/^END=//;
         } else {
             @arr[7] =~ s/^.*;END=//;
         }
         @arr[7] =~ s/;.*$//;
         printf "%s %s %s\n", @arr[0], @arr[1], @arr[7];
     }' <qq.in
2 118610455 118610566
1 859214 860180

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

perl -ne '{@arr=split;if (@arr[7] =~ /^END=/) {@arr[7] =~ s/^END=//;} else {@arr[7] =~ s/^.*;END=//;} @arr[7] =~ s/;.*$//; printf "%s %s %s\n", @arr[0], @arr[1], @arr[7];}' <qq.in

Как это работает, просто понимаешь.split дает массив элементов в строке, и вам просто нужно немного изменить число 7.

Если оно начинается с END=, просто избавьтесь от этого бита.В противном случае избавьтесь, если все, вплоть до ;END=.

Затем избавьтесь от всего после первого ; (в уже измененной версии, в которой бит N равен END=N наначало).

Затем просто распечатайте три требуемых значения.


Подумав об этом еще немного, может быть, лучше что-то немного проще, например:

pax> perl -ne '{
        ($a,$b,$x,$x,$x,$x,$x,$c,$x) = split;
        $c = ";$c";
        $c =~ s/^.*;END=//;
        $c =~ s/;.*$//;
        print "$a $b $c\n";
    }' <qq.in

или эквивалентный однострочный:

perl -ne '{($a,$b,$x,$x,$x,$x,$x,$c,$x)=split;$c=";$c";$c=~s/^.*;END=//;$c=~s/;.*$//;print "$a $b $c\n";}' <qq.in
0 голосов
/ 20 декабря 2011

Используйте sed:

$ cat input | sed -e 's/^\([0-9]\+\) \+\([0-9]\+\) .*\<END=\([0-9]\+\).*/\1 \2 \3/'
...