Grava em um arquivo cujo nome é uma string correspondente em um script sed

1

Tenho protocolos de reunião com tarefas a serem executadas, cada uma iniciando com a palavra-chave TODO e terminando com D/nameOfAssignee , assim:

Meeting 2017/03/22
some stuff
TODO task for philipp D/philipp

some more stuff

TODO task for jane D/jane
TODO task for joe D/joe

some other stuff TODO Another
task for Philipp
D/philipp

still
more
stuff

TODO Yet another
task for jane   D/jane

Agora quero obter um arquivo philipp.txt :

task for philipp
Another task for Philipp

e um arquivo jane.txt :

task for jane
Yet another task for jane

e um arquivo joe.txt :

task for joe

Eu faço isso com sed :

sed -n '/TODO/!d
  :l
  /D\//bw
  N
  bl
  :w
  s/.*TODO *//
  s/\n/ /g
  s_ *D/philipp__w philipp.txt
  s_ *D/joe__w joe.txt
  s_ *D/jane__w jane.txt
' tasks.txt

Isso funciona, mas para cada possível cessionário, eu preciso de uma linha idêntica no script, que começa a ficar irritante. Na documentação, não encontro uma maneira de usar uma substring correspondente à regex no nome do arquivo, como:

s_ *D/\(.*\)__w .txt (Isto não funciona! Tudo está escrito em um arquivo chamado !)

Existe outra possibilidade de primeiro gerar o script que eu possa usar em uma segunda execução com geração automática dessas linhas para cada responsável?

Ou é sed simplesmente a ferramenta errada e devo fazer coisas assim em python ?

    
por Philippos 27.03.2017 / 11:06

4 respostas

1

Existe uma maneira de fazer o que você quer, mas só funciona com o GNU sed.

sed -rn '/TODO/!d 
  :l
  /D\//bw
  N
  bl
  :w
  s/.*TODO *//
  s/\n/ /g
  s_(.*) *D/(.*)_echo  >> .txt_e
' tasks.txt

O segredo é a opção e especial no comando de substituição que executa o conteúdo do espaço de padrão como código de shell. Observe também o uso de -r para poder usar o agrupamento.

Os créditos vão para link

    
por 27.03.2017 / 14:37
1

tente isso ...

awk '{F=0;for(i=2;i<=NF;i++){if($(i-1)~/TODO/){F=1}if(F){printf("%s ",$i)}}printf("\n")}' RS="D/" tasks.txt | awk '{print > $NF".txt"}'
    
por 27.03.2017 / 11:14
1

Eu acho que você deveria escrever um roteiro. Pelo menos seria mais fácil manter e documentar do que uma longa sequência de transformações de sed (mas esse é o meu ponto de vista, você pode discordar).

Aqui está uma proposta do Perl:

#!/usr/bin/perl -n
#

sub printTodo {
    my ($todo,$person) = @_;
    my $file;
    open($file, ">>$person.txt");
    print $file "$todo\n";
    close($file);
}

if (/TODO (.*)D\/(\S*)/) {
    printTodo($1,$2);
} elsif (/TODO (.*)/) {
    $found = "$1 ";
} elsif (/(.*)D\/(\S*)/) {
    $found .= $1;
    printTodo($found,$2);
    $found = undef;
} elsif ($found) {
    chomp $_;
    $found .= "$_ ";
}

Supondo que você salve este script como script.pl e o relatório de sua reunião como meeting , chame assim: ./script.pl < meeting .

    
por 27.03.2017 / 11:32
1

Perl

Slurp tasks.txt e observe as seqüências de caracteres que começam com TODO e procure o mais próximo D/ , e podemos até pular para as novas linhas, para que surja a necessidade de fazê-lo. m//s .

Um novo recurso é que, se formos executá-lo uma segunda vez, os arquivos *.txt gerados não serão anexados, mas começarão novamente em cada rodada. Portanto, por construto, eles nunca enfrentarão a síndrome do tamanho fugitivo.

perl -MFatal=open -l -0777ne '
  do{open my $fh, $h{$2}++ ? ">>" : ">", "$2.txt"; print $fh $1 =~ y/\n/ /rs}
     while m|\bTODO\s*(.+?)\s*D/(\S+)|sg' tasks.txt

sed + ed

Como é ususal em tais casos, construímos dinamicamente um código ed para obter a saída. O que o novo recurso neste cenário é que o arquivo de dados em que o código ed iria operar é gerado dinamicamente a partir da mesma entrada.

Portanto, é como se dados + código fossem encontrados dentro do data.txt, que é separado e depois reunido como entradas de ed para gerar a saída de ed .

sed -n '
   /TODO/!d
   :l
   /D\//bw
   N
   bl
   :w
   s/.*TODO *//
   s/\n/ /g
  #<----------------------- ORIG --------------------->#

   H;s| *D/.*||w /tmp/data.txt
   g;s/.*\n//;x;s/\(.*\)\n.*//;x

   G;s/\n/&&/
   h
   / *D\/\(.*\)\n\(\(.*\n\)\{0,\}\)\n/!{
   s/.*[^ ] *D\/\(.*\n\)\n//
   x
   s/\n\n.*//
   s|\(.*[^ ]\) *D/|//w |;s|$|.txt|p;$!d;s/.*/q/p;q
   }

   g
   s/\n\n.*//
   s|\(.*[^ ]\) *D/|//W |;s|$|.txt|p;$!d;s/.*/q/p;q
' tasks.txt | ed -s - /tmp/data.txt

Advertência:

Certifique-se de que nenhum nome de pessoa a quem a tarefa seja atribuída seja chamado de "tarefas".

    
por 27.03.2017 / 17:35