Un tipo di conteggio

Linguaggi di programmazione: php, perl, python, C, bash, ecc.

Un tipo di conteggio

Messaggioda eb-ash » sabato 6 luglio 2019, 14:18

Avrei bisogno di un aiutino, non so come si possa esprimere a parola e quindi scusate il titolo molto generico.

Ho un file di testo che contiene:

A: 1
A (a): 2
B: 3
B (a): 2
B (b): 2
B (c): 1

Vorrei ottenere l'output:

A (a) : 3

B (a) (b) (c) : 8
si è vero uso un mac. Ma detesto i maccisti del web. Se la tirano, non ti aiutano, sono abituati ad avere la pappa fatta e non costruirsi le cose, e sono troppo pochi... quando serve non ci sono mai. Voglio imparare un po' di Bash per fare tante cose utili perchè questo sono qua... senza formazione specifica ma in fondo è unix che permette di fare le cose a pezzetti, no?
Avatar utente
eb-ash
Prode Principiante
 
Messaggi: 101
Iscrizione: febbraio 2019
Sesso: Maschile

Re: Un tipo di conteggio

Messaggioda UbuNuovo » martedì 9 luglio 2019, 15:43

Mi ero dimenticato di questo post, ora ho scritto il codice, ho usato AWK.
Come sei messo con AWK?
Vuoi un imboccata o il codice finito?

Prima prova da solo, poi semmai chiedi.
Come al solito ti consiglio di fare le prove su una struttura di dati semplice, come quella del tuo esempio.
il file 'dati.txt' contiene:
Codice: Seleziona tutto
A: 1
A (a): 2
B: 3
B (a): 2
B (b): 2
B (c): 1

Per prima cosa ti conviene individuare con sicurezza in quali campi sono distribuiti i dati:
Codice: Seleziona tutto
8-) awk -F'[ :]' '{print "$1",$1,"$2",$2,"$3",$3,"$4",$4}' dati.txt
$1 A $2  $3 1 $4
$1 A $2 (a) $3  $4 2
$1 B $2  $3 3 $4
$1 B $2 (a) $3  $4 2
$1 B $2 (b) $3  $4 2
$1 B $2 (c) $3  $4 1


Come vedi i valori da sommare sono presenti in "$3" o in "$4", questo dipende dalla presenza o meno dei valori in "$2"
Quindi devi usare il costrutto "if, else" per distinguere i due casi e assegnare i valori.
I valori numerici puoi assegnarli ad un array e sommarli direttamente, utilizzando l'operatore '+='
Codice: Seleziona tutto
array[indice]+=valore
i valori finali li stamperai ciclando l'array in END.
Per immagazzinare le stringhe (a), (b), (c); ho usato un'altro array con lo stesso indice del precedente, dove concateno il vecchio contenuto con il nuovo (contenuto in $2) in modo da poterne stampare il contenuto finale, dallo stesso ciclo del primo array.

Spero di essere stato comprensibile.
Nel caso in cui sia il primo a rispondere ad una richiesta di aiuto...chiunque abbia una soluzione migliore o anche solo diversa dalla mia è incoraggiato ad intervenire liberamente senza inviarmi alcun messaggio privato. In programmazione è basilare sapere che si può ottenere il medesimo risultato utilizzando metodi diversi.
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3374
Iscrizione: dicembre 2009
Desktop: Mate
Distribuzione: Ubuntu 14.04
Sesso: Maschile

Re: Un tipo di conteggio

Messaggioda eb-ash » giovedì 11 luglio 2019, 14:22

UbuNuovo Immagine ha scritto:Come sei messo con AWK?
Vuoi un imboccata o il codice finito?


Non mi oso... mi hai aiutato tanto finora :shy:

UbuNuovo Immagine ha scritto:Per prima cosa ti conviene individuare con sicurezza in quali campi sono distribuiti i dat.





Questa è la prima difficoltà che sto incontrando perchè nella realtà al posto di "A", "B" etc. ci sono nomi con varie parole... si tratta sempre di artisti che hanno inciso sotto pseudonimi quindi c'è di tutto....


Cmq cerco di studiare come affrontare il problema. Se non ci sono nuove da parte tua credo che mi farò sentire tra un migliaio di anni.... :verysad:
si è vero uso un mac. Ma detesto i maccisti del web. Se la tirano, non ti aiutano, sono abituati ad avere la pappa fatta e non costruirsi le cose, e sono troppo pochi... quando serve non ci sono mai. Voglio imparare un po' di Bash per fare tante cose utili perchè questo sono qua... senza formazione specifica ma in fondo è unix che permette di fare le cose a pezzetti, no?
Avatar utente
eb-ash
Prode Principiante
 
Messaggi: 101
Iscrizione: febbraio 2019
Sesso: Maschile

Re: Un tipo di conteggio

Messaggioda UbuNuovo » giovedì 11 luglio 2019, 15:24

Me lo immaginavo! Naturalmente i nomi possono essere di una due o più parole.
Devi fare in modo di avere dei separatori decenti trai vari campi, altrimenti per un programma è impossibile distinguere dove comincia un campo e ne finisce un altro.

Quando avrai i dati con la sintassi giusta puoi usare un metodo tipo questo:
Codice: Seleziona tutto
awk -F'[ :]' '{if($4==""){arr[$1]+=$3}else{arr[$1]+=$4;arrp[$1]=arrp[$1]" "$2;}} END {for (var in arr) print var arrp[var]" : " arr[var]}' dati.txt

provo:
Codice: Seleziona tutto
8-) awk -F'[ :]' '{if($4==""){arr[$1]+=$3}else{arr[$1]+=$4;arrp[$1]=arrp[$1]" "$2;}} END {for (var in arr) print var arrp[var]" : " arr[var]}' dati.txt
A (a) : 3
B (a) (b) (c) : 8
8-)
Nel caso in cui sia il primo a rispondere ad una richiesta di aiuto...chiunque abbia una soluzione migliore o anche solo diversa dalla mia è incoraggiato ad intervenire liberamente senza inviarmi alcun messaggio privato. In programmazione è basilare sapere che si può ottenere il medesimo risultato utilizzando metodi diversi.
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3374
Iscrizione: dicembre 2009
Desktop: Mate
Distribuzione: Ubuntu 14.04
Sesso: Maschile

Re: Un tipo di conteggio

Messaggioda eb-ash » sabato 13 luglio 2019, 12:55

Codice: Seleziona tutto
a=$(sed -e "s/ /∑/g" -e "s/:∑/: /g" -e "s/∑(/ (/g" DATI.txt)

echo $a| awk -F'[ :]' '{if($4==""){arr[$1]+=$3}else{arr[$1]+=$4;arrp[$1]=arrp[$1]" "$2;}} END {for (var in arr) print var arrp[var]" : " arr[var]}' DATI2.txt |sed -e "s/∑/ /g"


Va molto bene! Riesco a mettere ogni genere di parole sostituendo gli spazi vuoti con un carattere sentinella. Mi piacerebbe evitare il salvataggio su file, il "DATI2.txt" con un'altra variabile ma non so come fare
si è vero uso un mac. Ma detesto i maccisti del web. Se la tirano, non ti aiutano, sono abituati ad avere la pappa fatta e non costruirsi le cose, e sono troppo pochi... quando serve non ci sono mai. Voglio imparare un po' di Bash per fare tante cose utili perchè questo sono qua... senza formazione specifica ma in fondo è unix che permette di fare le cose a pezzetti, no?
Avatar utente
eb-ash
Prode Principiante
 
Messaggi: 101
Iscrizione: febbraio 2019
Sesso: Maschile

Re: Un tipo di conteggio

Messaggioda UbuNuovo » sabato 13 luglio 2019, 16:35

Sempre allo stesso modo: $(...)
Codice: Seleziona tutto
risultati=$(awk -F'[ :]' '{if($4==""){arr[$1]+=$3}else{arr[$1]+=$4;arrp[$1]=arrp[$1]" "$2;}} END {for (var in arr) print var arrp[var]" : " arr[var]}' <<< "$a" | sed -e 's/∑/ /g')


Però, invece di aggiungere e togliere separatori continuamente, ti conviene ottenere un file che ti faccia da database, che abbia tutti i separatori, poi solo da ultimo, per il risultato finale, sostituisci i separatori che non vuoi.

Quando ti arriva un nuovo file lo aggiungi al file database e poi lavori solo su quello.
Nel caso in cui sia il primo a rispondere ad una richiesta di aiuto...chiunque abbia una soluzione migliore o anche solo diversa dalla mia è incoraggiato ad intervenire liberamente senza inviarmi alcun messaggio privato. In programmazione è basilare sapere che si può ottenere il medesimo risultato utilizzando metodi diversi.
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
 
Messaggi: 3374
Iscrizione: dicembre 2009
Desktop: Mate
Distribuzione: Ubuntu 14.04
Sesso: Maschile


Torna a Programmazione

Chi c’è in linea

Visualizzano questa sezione: 0 utenti registrati e 1 ospite