Como anexar alguma linha correspondente à linha anterior correspondida com sed?

3

Por exemplo, transferir abaixo

00:00:10.730
this presentation is delivered by the

00:00:13.230
Stanford center for professional

00:00:14.610
development okay so let's get started

00:00:25.500
with today's material so um welcome back

00:00:32.399
to the second lecture what I want to do

para

00:00:10.730 --> 00:00:13.230
this presentation is delivered by the

00:00:13.230 --> 00:00:14.610
Stanford center for professional

00:00:14.610 --> 00:00:25.500
development okay so let's get started

00:00:25.500 --> 00:00:32.399
with today's material so um welcome back

00:00:32.399
to the second lecture what I want to do
    
por brook hong 08.06.2017 / 12:56

3 respostas

1

Com a abordagem única gawk para arquivos relativamente pequenos (por tamanho):

awk 'BEGIN{ RS=""; FS="[[:space:]]+" }
     {   c++; 
         a[c]["t"]=$1; 
         a[c]["s"]=substr($0,length($1)+2) 
     }
     END { 
         len=length(a); 
         for(i=1;i<=len;i++) { 
             if((i+1)<=len){ printf("%s --> %s\n%s\n\n",a[i]["t"],a[i+1]["t"],a[i]["s"]) } 
             else { printf("%s\n%s\n",a[i]["t"],a[i]["s"]) }
         } 
     }' file

A saída:

00:00:10.730 --> 00:00:13.230
this presentation is delivered by the

00:00:13.230 --> 00:00:14.610
Stanford center for professional

00:00:14.610 --> 00:00:25.500
development okay so let's get started

00:00:25.500 --> 00:00:32.399
with today's material so um welcome back

00:00:32.399
to the second lecture what I want to do
    
por 08.06.2017 / 13:55
1

Por motivos de clareza de código, estamos usando GNU sed :

sed -nE '

   /^([0-9][0-9]:){2}[0-9]+[.][0-9]+/!{p;d;}

   h;:a
      $bb;n;H
   /^([0-9][0-9]:){2}[0-9]+[.][0-9]+/!ba

   :b
   x
   y/\n_/_\n/
   s/^([^_]*)_(.*)_([^_]*)$/ ---> _/
   y/\n_/_\n/

   p;g;$!s/^/\n/;D

' yourfile

Resultados

00:00:10.730 ---> 00:00:13.230
this presentation is delivered by the

00:00:13.230 ---> 00:00:14.610
Stanford center for professional

00:00:14.610 ---> 00:00:25.500
development okay so let's get started

00:00:25.500 ---> 00:00:32.399
with today's material so um welcome back

00:00:32.399
to the second lecture what I want to do

Explicação

  • Mantemos o intervalo de linhas do número para o próximo número.
  • Então, no final do intervalo, a última parte é adiantada e o intervalo é impresso, também o espaço do padrão é eliminado e o final do intervalo é usado para preenchê-lo e, em seguida, usando esse valor do espaço padrão, o controle é transferido para o topo do código sed para iniciar o ciclo novamente a partir do fim atual do intervalo até o próximo número ou até atingirmos o eof.
por 08.06.2017 / 16:39
1

Com o GNU sed e tac :

tac file | \
sed -E '/^[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}$/ { H; x; s/^\n//; s/\n/ --> /; }' | \
tac

O mesmo poderia ser escrito com o tradicional sed (ou seja, sem -E ), mas seria mais detalhado.

Com o GNU awk e tac :

tac file | \
gawk --re-interval '
    /^[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3} --> / { old = $1 }
    /^[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}$/ { if(old != "") $0 = $0 " --> " old; old = $1 }
    1' | \
tac

Observe que a versão awk pode manipular intervalos de tempo, como 00:00:14.610 --> 00:00:25.500 no arquivo de entrada, enquanto a versão sed é enganada por eles.

Note também que tac pode ser emulado com sed :

sed -n '1!G; $p; h'

ou assim:

sed '1!G; h; $!d'

No entanto, os dois formulários carregarão todo o arquivo de entrada na memória, por isso não são muito eficientes.

Resultado:

00:00:10.730 --> 00:00:13.230
this presentation is delivered by the

00:00:13.230 --> 00:00:14.610
Stanford center for professional

00:00:14.610 --> 00:00:25.500
development okay so let's get started

00:00:25.500 --> 00:00:32.399
with today's material so um welcome back

00:00:32.399
to the second lecture what I want to do
    
por 08.06.2017 / 13:39