Eu quero produzir certas linhas de uma planilha para um arquivo diferente, se eles contiverem um número que é um maior do que na célula acima [duplicado]

0

Eu tenho um arquivo csv grande parecido com este:

SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,2,SomeData  
SomeData,SomeData,3,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,2,SomeData  
SomeData,SomeData,3,SomeData  
SomeData,SomeData,4,SomeData  
SomeData,SomeData,5,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  

Eu quero criar um novo arquivo csv que contém apenas linhas em que o terceiro valor faz parte de um conjunto, ou seja, se o valor no terceiro campo da linha abaixo for um maior, quero que ambas as linhas sejam incluídas. / p>

Então, no exemplo acima, eu só quero que as linhas 2-4 e 8-12 sejam salvas em um novo arquivo.

Estou com dificuldades para descobrir como grep procurar esse padrão.

Alguma idéia?

Obrigado

    
por Andrew Jennings 02.02.2017 / 14:28

2 respostas

1

Arquivos CSV são complicados. Partindo do pressuposto de que Somedata é um campo de dados corretamente citado que pode conter vírgulas, podemos substituir o delimitador por algo que definitivamente não está ocorrendo nos dados, por exemplo, um caractere de tabulação ( $'\t' na maioria dos shells modernos) ( você vai mudar isso para algo que você sabe que funciona). Se os campos de dados estiverem livres de vírgulas, ignore os csvformat bits aqui.

Usando csvkit :

$ csvformat -D$'\t' data.csv
SomeData        SomeData        1       SomeData
SomeData        SomeData        1       SomeData
SomeData        SomeData        2       SomeData
SomeData        SomeData        3       SomeData
SomeData        SomeData        1       SomeData
etc.

Podemos passar isso para um script awk que faz o trabalho real de encontrar os grupos.

NR > 1 && $3  == count + 1 {
    # This line is part of the set.

    ++count;        # We expect this value on the next line.
    ++set_size;     # This is the number of lines in the set.

    # Output previous line and remember this line.
    print previous_line;
    previous_line = $0;

    # Continue with next line.
    next;
}

set_size > 0 && $3 != count + 1 {
    # This line is not part of the set, but we're currently tracking a
    # set.  This means that the set ended, so output the last line of
    # the set.

    print previous_line;
    set_size = 0;
}

{
    # This line might be part of the next set.

    count = $3;
    previous_line = $0
}

Executando:

$ csvformat -D$'\t' data.csv | awk -F$'\t' -f script.awk
SomeData        SomeData        1       SomeData
SomeData        SomeData        2       SomeData
SomeData        SomeData        3       SomeData
SomeData        SomeData        1       SomeData
SomeData        SomeData        2       SomeData
SomeData        SomeData        3       SomeData
SomeData        SomeData        4       SomeData
SomeData        SomeData        5       SomeData

Depois, basta recuperá-lo no formulário padrão delimitado por vírgulas:

$ csvformat -D$'\t' data.csv | awk -F$'\t' -f script.awk | csvformat -d$'\t'
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData

Se os dados estiverem livres de vírgulas dentro dos campos de dados, você poderá deixar csvformat completamente:

$ awk -F',' -f script.awk data.csv
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData
    
por 02.02.2017 / 15:28
1

Supondo que os dados estejam no arquivo datafile , você pode usar awk para esse processamento. (Você não pode usar grep porque lida apenas com linhas únicas de contexto.)

awk -F, '
    # Initially we are not in a block
    BEGIN { inblock=0 }

    # If the third field is greater than that on the previous line, print
    # it. But if we were not already in a block then print the saved line
    # too - and mark that we are now in a block
    NR>1 && $3>third { if (!inblock) { print line; inblock=1 } print $0 }

    # If we are in a block and the third field is smaller that the previous
    # line value, drop out of the block
    inblock && $3<=third { inblock=0 }

    # Save the values each time around
    {third=$3; line=$0 }
' datafile
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData
    
por 02.02.2017 / 14:57

Tags