2017-02-19 18 views
1

У меня есть файл с несколькими линиями в следующей форме:прерывистых линий в заданных точках с AWK

name1 a1 b3 c6 a3 b4 c9 
name2 a7 b8 c7 a9 b10 c13 
name3 a12 b9 c8 
name4 a4 b34 c19 a7 b2 c10 a3 b5 c67 

Мне нужно разбить строки после буквы повторить (т.е. после каждого а, б, в), но имеют оригинальное имя (поле 1) сохраняется:

name1 a1 b3 c6  
name1 a3 b4 c9 
name2 a7 b8 c7  
name2 a9 b10 c13 
name3 a12 b9 c8 
name4 a4 b34 c19 
name4 a7 b2 c10  
name4 a3 b5 c67 

Я пытался что-то вдоль линий:

awk -F"\t" '{ for (i=2;i<=NF;i++) print $1"\t"$i }' file 

но i++ включает в себя каждое поле, есть ли способ их сгруппировать?

спасибо.

+0

Может письма выйти из строя? 'c2'' a3' 'b1'? –

+0

@Mark Setchell да они могут – starter5

+0

Будут ли они всегда повторять или могут быть линии без повторения? –

ответ

0

@ starter5: Попытка:

awk 'BEGIN{V["a"];V["b"];V["c"]} /name/{R=$0;next} {Q=$0;gsub(/[[:digit:]]/,"",Q)} (Q in V){if(!W[Q]++){A++}} $0{if(A==1 && $0 && R){$0=R OFS $0};printf("%s %s",$0,(A==3?"\n":OFS));;if(A==3){A="";delete W}}' RS='[ +|\n]' Input_file 

Ниже приводится NON-один вкладыш формы раствора слишком здесь.

awk 'BEGIN{ 
       V["a"]; 
       V["b"]; 
       V["c"] 
      } 
       /name/{ 
         R=$0; 
         next 
         } 
      { 
       Q=$0; 
       gsub(/[[:digit:]]/,"",Q) 
      } 
       (Q in V){ 
           if(!W[Q]++){ 
               A++ 
              } 
         } 
       $0  { 
           if(A==1 && $0 && R){ 
                 $0=R OFS $0 
                }; 
           printf("%s %s",$0,(A==3?"\n":OFS));; 
           if(A==3)   { 
                 A=""; 
                 delete W 
                } 
         } 
    ' RS='[ +|\n]' Input_file 

Итак, давайте говорить, что мы имеем следующие input_file (где я изменил последнюю строку), чтобы проверить, если, б, не идут в последовательности, так что он не будет нарушать линию до трех из них нашли, есть Посмотри на это и дайте мне знать.

cat Input_file 
name1 a1 b3 c6 a3 b4 c9 
name2 a7 b8 c7 a9 b10 c13 
name3 a12 b9 c8 
name4 a4 b34 a19 a7 b2 c10 a3 b5 c67 

Результат будет следующим.

name1 a1 b3 c6 
name1 a3 b4 c9 
name2 a7 b8 c7 
name2 a9 b10 c13 
name3 a12 b9 c8 
name4 a4 b34 a19 a7 b2 c10 
name4 a3 b5 c67 
+0

Отображаемый _output_ не совпадает с показателем OP или того, что я получаю, так же, как OP, запустив 'awk' _program_. Должно быть три отдельных строки 'name4', и вам показывают только два. – user3439894

+0

@ user3439894: Просьба четко прочитать мое утверждение вместе с OP, поэтому я внес изменения в Input_file и не сделал все a, b, c таким образом, чтобы он печатал строки до тех пор, пока не найдет все 3 совпадения a, b, c в строках. Если мы используем точный файл, подобный OP, он также должен работать с этим. Надеюсь, это поможет. – RavinderSingh13

0

Мне нужно разбить строки после буквы повторить (т.е. после каждого а, б, в), но оригинальное название (поле 1) сохраняется:

Вход

$ cat file 
name1 a1 b3 c6 a3 b4 c9 
name2 a7 b8 c7 a9 b10 c13 
name3 a12 b9 c8 
name4 a4 b34 c19 a7 b2 c10 a3 b5 c67 

Выход

$ awk 'function _p(){print $1,s; s=""; split("",p)}{for(i=2; i<=NF; i++){ c=substr($i,1,1);if(c in p)_p(); s = (s?s OFS:"") $i; p[c] }_p()}' file 
name1 a1 b3 c6 
name1 a3 b4 c9 
name2 a7 b8 c7 
name2 a9 b10 c13 
name3 a12 b9 c8 
name4 a4 b34 c19 
name4 a7 b2 c10 
name4 a3 b5 c67 

Лучше Читаемая версия

awk ' 
    function _p() 
    { 
       print $1,s; 
       s=""; 
       split("",p) 
    } 
    { 
     for(i=2; i<=NF; i++) 
     { 
       c=substr($i,1,1); 
       if(c in p)_p(); 
       s = (s?s OFS:"") $i; 
       p[c] 
     } 
     _p() 
    } 
    ' file 

ИЛИ

$ awk 'function _p(){print $1,s; s=p=""}{for(i=2; i<=NF; i++){ c=substr($i,1,1); if(c==p)_p(); s = (s?s OFS:"") $i; if(!p)p=c }_p()}' file 
name1 a1 b3 c6 
name1 a3 b4 c9 
name2 a7 b8 c7 
name2 a9 b10 c13 
name3 a12 b9 c8 
name4 a4 b34 c19 
name4 a7 b2 c10 
name4 a3 b5 c67 

Лучше Читаемая версия

awk ' 
    function _p() 
    { 
     print $1,s; 
     s=p="" 
    } 
    { 
     for(i=2; i<=NF; i++) 
     { 
      c=substr($i,1,1); 
      if(c==p)_p(); 
      s = (s?s OFS:"") $i; 
      if(!p)p=c 
     } 
      _p() 
    }' file 
0
{         # for any record 
    printf $1      # print name 
    c=substr($2,1,1);    # first letter of group 
    printf OFS $2     # first part of first group 
    for(i=3; i<=NF; i++) {   # for all the rest fields 
     if(index($i,c) != 1)  # if next group has not started 
      printf OFS $i   # print this part on same line 
     else      # otherwise 
      printf ORS $1 OFS $i # print name and this part on next line 
    }        # done for all fields 
    printf ORS      # move to next line 
}         # done for this record 

Это не работает, если какая-либо буква повторяет в пределах группы. Например, он не будет работать для a3 b5 a4 c6 a5 b6 a0 b9, где присутствуют группы a b a c.

Это может работать как:

awk '{ printf $1; c=substr($2,1,1); printf OFS $2; for(i=3;i<=NF;i++) if(index($i,c)!=1) printf OFS $i; else printf ORS $1 OFS $i; printf ORS}' file 

 Смежные вопросы

  • Нет связанных вопросов^_^