Transcreva uma coluna csv no awk, respondendo por campos vazios

1

Digamos que eu tenha um arquivo csv com várias colunas. NF não é constante. No momento, para substituir colunas > 4 com letras minúsculas, estou fazendo:

#!/usr/bin/awk
#call with 'awk -f lowercase.awk in.csv > out.csv'
BEGIN {
    OFS=",";
    FPAT="([^,]+)|(\"[^\"]+\")";
}
{
    for (i=1; i<=NF; i++){
        if(i>4 && $i){
            $i = tolower($i);
        }
    }
    print $0;
}

Mas isso não leva em conta os separadores de campos adjacentes (colunas vazias denotadas por vírgulas repetidas) no arquivo csv como ,,,, . Como posso levar isso em conta? Eu não gosto das soluções aqui porque elas não generalize bem (há muita verificação condicional, e minha aplicação no mundo real tem NF > 40 e < 70).

Teste de unidade:

in.csv

apple,orange,banana,cherry,MELON,"Fruit salad",grape
"Lots of vegtables",CUCUMBER,carrot,potato,RADISH,BeetrOOT
Bread,BAGEL,,,,Croissant

out.csv

apple,orange,banana,cherry,melon,"fruit salad",grape
"Lots of vegtables",CUCUMBER,carrot,potato,radish,beetroot
Bread,BAGEL,,,,croissant
    
por Escher 12.08.2015 / 11:04

2 respostas

1

Fácil por sed

sed 's/\(\([^,]*,\)\{4\}\)\(.*\)/\L/' file.csv

se você não gosta de escapar de caracteres, você pode modificar o script (para o GNU sed):

sed -r 's/(([^,]*,){4})(.*)/\L/' file.csv

que localizam quatro grupos de quaisquer (0 incluídos) símbolos não-vírgula seguidos por vírgula e deixam-no inalterado ( ) e trocam todos na parte restante da cadeia ( ) para uma versão inferior. Ou por cut e paste

paste -d, <(cut -d, -f-4 file.csv) <(cut -d, -f5- file.csv | tr '[[:upper:]]' '[[:lower:]]')
    
por 12.08.2015 / 11:31
1

Eu posso ter entendido mal algo sobre a questão, então, por favor, me perdoem se eu tiver. Parece, no entanto, que você deve ser capaz de simplesmente tolower de qualquer campo maior que 4 (ou 40, ou o que você escolher). Por exemplo:

BEGIN {
    OFS = ","
   }
{
    for (i = 4 ; i <= NF ; i++) {
        $i = tolower($i)
        }
    $1 = $1
    print
}

Afinal, tolower(*some empty field*) é simplesmente um campo vazio. Existe uma razão pela qual isso não funcionaria?

Editar: minha saída:

apple,orange,banana,cherry,melon,"fruit salad",grape
"Lots of vegtables",CUCUMBER,carrot,potato,radish,beetroot
Bread,BAGEL,,,,croissant
    
por 02.11.2015 / 19:21