Obtenha uma lista de nomes de arquivo e compare com um arquivo csv ao adicionar 2ª e 3ª coluna da mesma 1ª coluna

Aug 15 2020

Eu tenho um arquivo csv parecido com este:

user1,400,300
user2,250,250
user3,400,300
user1,400,300
user4,400,300
user2,250,250

e um diretório que tem um arquivo vazio com o nome do usuário

$ ls /dir/*
/dir/user1
/dir/user2

Quero procurar o arquivo e salvar seu nome em uma matriz, em seguida, pesquisar esse nome por meio do registro csv, adicionar todas as 2ª e 3ª colunas desse nome, para todas as linhas, e também mostrar se o valor do usuário excede ex: 400

Resultados de exemplo:

user1,1400
user1 has exceed 400
user2,1000
user2 has exceed 400

Eu realmente aprecio alguma ajuda. Atualmente estou tentando fazer isso, mas sem resultados:

shopt -s nullglob
cd /dir/
ARRAY=(*)

for ((i=0; i<${#ARRAY[@]}; i++)); do
    name=${ARRAY[i]} awk ' BEGIN{FS=OFS=","} {$name += (($2+$3))} 
    END{for (j in a) printf "%s | %0.2f\n", j, a[j]}
    ' /dir.csv
done
cd

Ou talvez haja um método mais simples onde não há necessidade de salvar o nome do arquivo em uma matriz?

Respostas

Quasímodo Aug 15 2020 at 20:13

Eu sugiro

for f in dir/*; do awk -F ',' '$1==f{s+=$2+$3}END{print f","s;if(s>400)print f" has exceeded 400"}' f="$(basename "$f")" dir.csv; done

Ou em forma equivalente desenrolada:

for f in dir/*; do 
    awk -F ',' '
        $1==f{s+=$2+$3}
        END{
            print f","s
            if(s>400)print f" has exceeded 400"
        }
    ' f="$(basename "$f")" dir.csv
done

Para cada arquivo interno dir/, seu nome de base (ou seja, o nome sem o caminho) é passado para o script awk como a variável f.

No script awk, o separador de campo é definido como vírgula com -F ','. Então, se o primeiro campo de dir.csvfor igual a f, a soma do 2º e 3º campos é adicionada a s. Se a soma for superior a 400, a mensagem será incluída.