[Risolto] Un tipo di conteggio

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Avatar utente
eb-ash
Prode Principiante
Messaggi: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

[Risolto] Un tipo di conteggio

Messaggio da eb-ash »

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
Ultima modifica di eb-ash il martedì 30 luglio 2019, 3:25, modificato 2 volte in totale.
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
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4444
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: Un tipo di conteggio

Messaggio da UbuNuovo »

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.
Salva l'Ucraina! 🇺🇦
Avatar utente
eb-ash
Prode Principiante
Messaggi: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

Re: Un tipo di conteggio

Messaggio da eb-ash »

Non mi oso... mi hai aiutato tanto finora :shy:
UbuNuovo [url=https://forum.ubuntu-it.org/viewtopic.php?p=5141890#p5141890][img]https://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] 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
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4444
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: Un tipo di conteggio

Messaggio da UbuNuovo »

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-) 
Salva l'Ucraina! 🇺🇦
Avatar utente
eb-ash
Prode Principiante
Messaggi: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

Re: Un tipo di conteggio

Messaggio da eb-ash »

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
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4444
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: Un tipo di conteggio

Messaggio da UbuNuovo »

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.
Salva l'Ucraina! 🇺🇦
Avatar utente
eb-ash
Prode Principiante
Messaggi: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

Re: Un tipo di conteggio

Messaggio da eb-ash »

Devo dire che ho trovato un problema. Questo awk

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')
mi risulta incompatibile con questo

Codice: Seleziona tutto

awk -F";" '{a[$1]+=$NF} END {for(i in a)print i": "a[i];}' < <(sed -e 's/   /;/' -e 's@\([0-9]\+\) \(.*\)@\2;\1@'
In pratica funziona solo il primo che antepongo e ottengo un ouput con i risultati buoni del primo ma con la mancanza di risultati del secondo.

Forse si può fare la stessa cosa senza awk?
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
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4444
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: Un tipo di conteggio

Messaggio da UbuNuovo »

:? ???
Non sono un indovino.
Salva l'Ucraina! 🇺🇦
Avatar utente
eb-ash
Prode Principiante
Messaggi: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

Re: Un tipo di conteggio

Messaggio da eb-ash »

Ok, non era chiaro...

Volevo dire, se secondo te il tuo awk si può integrare con il mio. MIo... si fa per dire, quello che mi avevi preparato è che è il motore di tutto lo script. Secondo te è fattibile?

Sto provando a mescolarli nel pentolone... ti farò sapere se ci riuscirò...
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: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

Re: Un tipo di conteggio

Messaggio da eb-ash »

Ho capito cosa mi serve, Ubu! Niente pentolone... mi serve solo escludere da un'awk le righe con una certa parola chiave e dall'altro awk le righe senza quella parola. Poi unire i due risultati. Forse riesco a farcela da solo...
eh la notte porta consiglio... hi hi..
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: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

Re: (Risolto) Un tipo di conteggio

Messaggio da eb-ash »

:woot: :woot: :woot: :woot: :woot:

Funziona perfettamente

era già perfetto, ho fatto un po' di pasticci io con i caratteri delimitatori. Mancanza di metodo.
Mi è molto servito questo schema per capire cosa sbagliavo

Codice: Seleziona tutto

 awk -F'[ :]' '{print "$1",$1,"$2",$2,"$3",$3,"$4",$4}'
Adesso filtra meravigliosamente un sacco di nomi complicati, senza che io debba modificare le mie abitudini nominatoriei!
L'unica cosa che ho dovuto fare e inserire prima

Codice: Seleziona tutto

 -e 's/;.*;/;/'
in modo da eliminare i tanti delimitatori dovuti alla miriade di casi particolari nei nomi dei miei file.

Non me lo permettono ma metterei cento faccine. Grazie, Ubu!
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
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4444
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: (Risolto) Un tipo di conteggio

Messaggio da UbuNuovo »

Bene! Sei sulla buona strada. Meno separatori ci sono e più è facile gestire i dati. :birra:

Quando chiedi supporto ricordati di fornire sempre più informazioni possibili su ciò che hai e su quello che vuoi ottenere (input, codice, output ottenuto, output desiderato).
Te sai sempre di cosa parli, chi cerca di aiutarti no.

"Risolto" mettilo tra parentesi quadrate, è una convenzione, utile per le ricerche.
Ciaux
Salva l'Ucraina! 🇺🇦
Avatar utente
eb-ash
Prode Principiante
Messaggi: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

Re: [Risolto] Un tipo di conteggio

Messaggio da eb-ash »

Ubu, sto cercando di modificare il tuo awk per ottenere una cosa diversa.


il file di testo sarebbe questo:

pippo pluto; 1
pippo pluto & paperino (a); 1
pippo pluto's paperino (b); 1



e vorrei ottenere questo:

pippo pluto (a) (b); 3
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
trekfan1
Moderatore Globale
Moderatore Globale
Messaggi: 23402
Iscrizione: domenica 21 maggio 2006, 10:51
Desktop: Gnome
Distribuzione: Ubuntu 23.10 e 24.04 (dev)
Sesso: Maschile
Località: Formigine (MO) | Accecante Asceta

Re: [Risolto] Un tipo di conteggio

Messaggio da trekfan1 »

Sei pregato di usare il tag CODE (tasto </> dell'editor completo) quando posti dei listati o dell'output, grazie e vedi di ricordarlo
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4444
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [Risolto] Un tipo di conteggio

Messaggio da UbuNuovo »

Sì, usa sempre il tag code per il codice, seleziona il testo e clicca il pulsante: (</>)

Per quanto riguarda quello che vuoi fare, non si può!
A quanto vedo, i nomi sono separati da ";".
Anche usando come altro separatore "&" e considerando le prime due parole del primo campo come nome_base, "pippo pluto" non sarà mai uguale a "pippo pluto's".
Si potrebbe usare l'apice ' come ulteriore separatore, in modo da poter fare il conteggio sui nomi formati dai primi due campi.
per esempio:

Codice: Seleziona tutto

8-) cat dati.txt
pippo pluto; 1
pippo pluto & paperino (a); 1
pippo pluto's paperino (b); 1
eta beta blabla; 3
archimede pitagorico; 1
eta beta naftalina; 2

8-) awk -F"[ ;'&]" '{nome=$1" "$2;ar[nome]+=$NF}END{for (var in ar) print var,ar[var]}' dati.txt
archimede pitagorico 1
pippo pluto 3
eta beta 5
Ma i nomi_base potrebbero consistere in una sola o più di due parole, di conseguenza non ha senso usare quel codice.
Non mi metto a provare ad estrarre i valori tra parentesi, che possono trovarsi in campi diversi o mancare del tutto; non ne vale la pena!

L'unico modo (quasi) decente, sarebbe ciclare un ipotetico elenco di "nomi_base" e, in base a questi, cercare la sottostringa corrispondente per fare i conteggi.
Salva l'Ucraina! 🇺🇦
Avatar utente
eb-ash
Prode Principiante
Messaggi: 204
Iscrizione: lunedì 18 febbraio 2019, 18:02
Sesso: Maschile

Re: [Risolto] Un tipo di conteggio

Messaggio da eb-ash »

Va bene, risolverò con delle sottostringhe conosciute da tagliare via con sed. Grazie!

Mi studierò il tuo codice per capire di più di Awk. E' molto interessante.
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?
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 6 ospiti