Como fazer a formatação seguinte usando o script sed ou awk ou bash no linux

1

Suponha que eu tenha dois arquivos: file1 com conteúdo abaixo.

message_aaa.wav
  test 1 of 1
    test Label        : aaa
    test Sentence       : test aaa
    test String: test message
    Interpretation Score : 567
message_bbb.wav
  test 1 of 1
    test Label        : bbb
    test Sentence       : test bbb
    test String: test bbb
    Interpretation Score : 972
Message_ccc.wav
  test 1 of 1
    test Label        : ccc
    test Sentence       : ccc
    test String: test ccc
    Interpretation Score : 921     
   

file2 com conteúdo abaixo:

message_aaa.wav
  test 1 of 1
    test Label        : aaa
    test Sentence       : test aaa
    test String: test message
    Interpretation Score : 55
message_bbb.wav
  test 1 of 1
    test Label        : bbb
    test Sentence       : test bbb
    test String: test bbb
    Interpretation Score : 34
message_ccc.wav
  test 1 of 1
    test Label        : ccc
    test Sentence       : ccc
    test String: test ccc
    Interpretation Score : 12

Eu quero criar um arquivo CSV / xls , que terá 3 colunas como: A primeira coluna será o nome dos arquivos .wav de file1
A segunda coluna será "Pontuação de interpretação" from file1
A terceira coluna será "Interpretation Score" from file2
como abaixo.

message_aaa.wav,567,55
message_bbb.wav,972,34
message_ccc.wav,921,12
    
por AVJ 14.03.2016 / 14:48

3 respostas

0

Aqui está um script perl que faz o trabalho. Ele lê stdin e extrai os nomes dos arquivos para usar como chave para um array com hash chamado %wavfiles . A estrutura de dados particular usada é um hash-de-arrays, um array com hash onde cada elemento é uma lista (ou seja, um array) contendo um ou mais valores.

Quando houver uma linha correspondente à regex /Interpretation Score/ AND se $filename não estiver vazia, ela usará split() para extrair a pontuação de interpretação e enviá-la para a matriz contida em $wavfiles{$filename} . Em seguida, ele limpa $filename para evitar que dados espúrios sejam adicionados a essa chave.

Quando não há mais entrada a ser lida, ela imprime o conteúdo dos hash-of-arrays %wavfiles no formato CSV.

Este script funcionará com qualquer número de arquivos de entrada, de qualquer tamanho. Ele trata todos os nomes de arquivos especificados na linha de comando e / ou todos os dados enviados de stdin como um fluxo de entrada.

A ordem da entrada é significativa - ela afeta diretamente a ordem dos Interpretation Scores na saída (por exemplo, se vê 567 antes de 55, que é a ordem em que exibirá esses valores. e vice-versa).

O script não está limitado a apenas dois Interpretation Scores para cada nome de arquivo - ele imprimirá quantos ver para cada nome de arquivo, separados por vírgulas na ordem em que foram vistos.

#! /usr/bin/perl

use strict;

my %wavfiles = ();
my $filename = '';

while(<>) {
    chomp;    # strip line-feed from end of line

    $filename = $_ if (m/\.wav$/);

    if ((m/Interpretation Score/) && (! -z $filename)) {
        my (undef,$score) = split /: /;     # split input line on ': '
        push @{ $wavfiles{$filename} }, $score;
        $filename = '';
    };
}   

foreach $filename (keys %wavfiles) {
    print "$filename,", join(",",@{ $wavfiles{$filename} }),"\n";
}   

A saída usando sua entrada de amostra é:

$ ./interpscore.pl file1 file2
message_bbb.wav,972,34
Message_ccc.wav,921
message_aaa.wav,567,55
message_ccc.wav,12

Observe que as chaves hash, como os nomes de arquivos, fazem distinção entre maiúsculas e minúsculas, e é por isso que existe uma entrada para Message_ccc.wav (com maiúscula M) e message_ccc.wav (com minúscula m). em seus arquivos de entrada. Você precisa editar seus arquivos de entrada para que os nomes dos arquivos fiquem consistentes - depois disso, a saída será:

$ ./interpscore.pl file1 file2
message_aaa.wav,567,55
message_ccc.wav,921,12
message_bbb.wav,972,34
    
por 15.03.2016 / 02:49
1

Algo parecido com isso com awk :

awk '/^[mM]essage_.*.wav/{
    n=NR+5;i=tolower($1)
}
n==NR{
    a[i]=a[i]","$4
}
END{
    for ( i in a){
        print i""a[i]
    }
}' file1 file2

Se a linha começar com [mM]essage_.*.wav , a variável n será definida como NR+5 (os números de linha em que Interpretation Score é o valor) e o nome do arquivo wav será salvo na variável i .

Quando n==NR e matriz com índice como i é criado e Interpretation Score ($ 4) é anexado a essa matriz.

END imprime todo o índice da matriz e seu valor conforme desejado.

Aqui eu assumi a linha Interpretation Score sempre como a quinta linha em cada teste.

    
por 14.03.2016 / 15:54
1
grep -e 'wav\|Inter' file1.txt | cut -d: -f2 | awk '{print $1}'| awk 'NR%2{printf $0",";next;}1' > file1new.txt
grep -e 'wav\|Inter' file2.txt | cut -d: -f2 | awk '{print $1}'| awk 'NR%2{printf $0",";next;}1' > file2new.txt
join -t, file1new.txt file2new.txt

    
por 14.03.2016 / 16:03