Codice: Seleziona tutto
Pippo: 2
Pippo pluto: 3
Paperino: 1
Topolino Pippo: 4
Codice: Seleziona tutto
Pippo (Pippo pluto): 5
Paperino: 1
Topolino Pippo: 4
Codice: Seleziona tutto
Pippo: 2
Pippo pluto: 3
Paperino: 1
Topolino Pippo: 4
Codice: Seleziona tutto
Pippo (Pippo pluto): 5
Paperino: 1
Topolino Pippo: 4
dove ? in un file ? in piu' file ? nell'output di grep ? in quello di uniq ?
In un solo file.
Uso bash, ho uno script che fa una ricerca tra i miei file, tratta le stringhe dei titoli e fa un elenco delle stringhe, una su ogni linea in ordine alfabetico e le stringhe uguali le somma, l’output lo salvo come testo. Adesso desideto sommare le stringhe come nell’esempio (perché iniziando con la stessa parola fanno parte dello stesso gruppo). Quindi il comando deve riconoscere solo le stringhe che iniziano con la prima parola uguale e spostarle sulla stessa linea e fare la somma dei valori. Poi le stringhe aggiunte le vorrei mettere dentro una parentesi.
Esatto, ma solo se Pippo è la prima parola della stringa. Il risultato è il gruppo delle stringhe che inizia con la parola chiave.DoctorStrange ha scritto: ↑domenica 12 febbraio 2023, 10:29Pippo è la chiave in una mappa chiave-valore. Fare una left outer join su mappe chiave-valore di quel tipo dovrebbe generare proprio il risultato atteso.
Occhio che sono terribilmente arrugginito sulla bash, comunque, ho giocato un po' con gli array facendo questo scripteb-ash ha scritto: ↑sabato 11 febbraio 2023, 19:18Ho
Vorrei ottenereCodice: Seleziona tutto
Pippo: 2 Pippo pluto: 3 Paperino: 1 Topolino Pippo: 4
Codice: Seleziona tutto
Pippo (Pippo pluto): 5 Paperino: 1 Topolino Pippo: 4
Codice: Seleziona tutto
#!/bin/bash
# Leggo e memorizzo in array le righe nomi
num=0
while read riga
do
righe[$num]=$riga
num=$(($num+1))
done < nomi
echo
num=$(($num-1))
i1=0
while [ $i1 -lt $num ]
do
if [ "${righe[$i1]+abc}" ] # verifico esistenza indice
then
IFS=':' read -a elem1 <<< ${righe[$i1]}
val1=${elem1[$((${#elem1[@]}-1))]}
IFS=' ' read -a parts <<< ${elem1[0]}
control=${parts[0]}
i2=$(($i1+1))
match=0
while [ $i2 -le $num ]
do
if [ "${righe[$i2]+abc}" ]
then
IFS=':' read -a elem2 <<< ${righe[$i2]}
val2=${elem2[$((${#elem2[@]}-1))]}
IFS=' ' read -a parts <<< ${elem2[0]}
verify=${parts[0]}
if [ $control = $verify ]
then
match=1
elem1[0]="${elem1[0]} (${elem2[0]})"
val1=$(($val1+$val2))
unset righe[$i2]
fi
i2=$(($i2+1))
else
i2=$(($i2+1))
fi
done
if [ $match -eq 1 ]
then
righe[$i1]="${elem1[0]}: $val1"
fi
i1=$((i1+1))
else
i1=$((i1+1))
fi
done
i1=0
while [ $i1 -le $num ]
do
if [ "${righe[$i1]+abc}" ] # verifico esistenza indice
then
echo "${righe[i1]}" >> colletta_nomi
fi
i1=$(($i1+1))
done
Codice: Seleziona tutto
NzP:~$ ls
leggi.sh nomi
NzP:~$ cat nomi
Pippo: 2
Pippo pluto: 3
Paperino: 1
Pippo Minnie: 1
Topolino Pippo: 4
NzP:~$ ./leggi.sh
NzP:~$ ls
colletta_nomi leggi.sh nomi
NzP:~$ cat colletta_nomi
Pippo (Pippo pluto) (Pippo Minnie): 6
Paperino: 1
Topolino Pippo: 4
NzP:~$
Codice: Seleziona tutto
temp 10 > /usr/bin/uniq -c prova
2 Pippo
3 Pippo pluto
1 Paperino
4 Topolino Pippo
temp 12 > awk '{print $1}' prova | /usr/bin/uniq -c
5 Pippo
1 Paperino
4 Topolino
questo è sicuramente vero ma bisogna sapere come fare per ottenere il risultato precisamente richiesto dall'OP (che è ciò che ha fatto @nuzzopippo). Se non si posta un codice in tal senso, tutto il resto sa un po' di fuffa, senza offesa per nessuno
Questo è poco ma sicuro!
Codice: Seleziona tutto
8-) cat file.txt
Pippo: 2
Pippo pluto: 3
Paperino: 1
Topolino Pippo: 4
8-) awk -F"[: ]" '{n_nomi[$1]+=$NF;if(NF > 2){cont[$1]=cont[$1]" ("$1" "$2")"}} END { for (key in n_nomi) { print key, cont[key] ": " n_nomi[key]}}' file.txt
Topolino (Topolino Pippo): 4
Pippo (Pippo ) (Pippo pluto): 5
Paperino (Paperino ): 1
8-)
Signori, non concordo con Voi, la domanda dello OP era chiara : si tratta di una manipolazione di stringa con somma di valori e nuova produzione di stringa con indicate le modalità, l'input/output sono fattori secondari, le motivazioni Sue.
Ok, in tal caso hai ragione, lo script non potrebbe funzionare il caso di spazi nei nomi ed, inoltre, sarebbe poco pratico per i potenziali "cumuli" di stringhe che possono verificarsi.UbuNuovo ha scritto: ↑lunedì 13 febbraio 2023, 18:43...Conosco il lavoro che sta facendo, ormai da parecchio tempo; deve catalogare file musicali e, sicuramente, i nomi non saranno topolino e pippo ma, molto probabilmente, saranno composti e probabilmente potrebbero avere separatori diversi o altre diversificazioni...
Ho fatto anche il mio script per divertimento, ma è in Programmazione/CSharp/Script, niente a che fare con la richiesta inizialenuzzopippo ha scritto: ↑lunedì 13 febbraio 2023, 18:22tutto sommato, è anche divertente dare risposte a quesiti del genere, non scriveremmo qui, altrimenti.
Codice: Seleziona tutto
#!/usr/bin/env dotnet-script
using System;
using System.Data;
DataTable dtTableInput = new DataTable();
dtTableInput.Columns.Add("PrimaParole", typeof(string));
dtTableInput.Columns.Add("Riga", typeof(string));
dtTableInput.Columns.Add("Count", typeof(Int16));
DataTable dtableOutput = new DataTable();
dtableOutput.Columns.Add("PrimaParole", typeof(string));
dtableOutput.Columns.Add("Riga", typeof(string));
dtableOutput.Columns.Add("Count", typeof(Int16));
void Input()
{
FileStream fs;
StreamReader strmReader = null;
string strLigne;
string[] strSplit, strSplit2;
DataRow dtRow;
try
{
// Leggere e memorizzare in array le righe nomi
fs = new FileStream("input.txt", FileMode.Open, FileAccess.Read);
strmReader = new StreamReader(fs, Encoding.UTF8);
while ((strLigne = strmReader.ReadLine()) != null)
{
// dividere in corrispondenza del carattere ':'
dtRow = dtTableInput.NewRow();
strSplit = strLigne.Split(new Char [] {':'});
dtRow["Count"] = Convert.ToInt16(strSplit[1]);
// dividere in corrispondenza del carattere ' '
strSplit2 = strSplit[0].Split(new Char [] {' '});
dtRow["PrimaParole"] = strSplit2[0];
dtRow["Riga"] = strSplit[0];
//
dtTableInput.Rows.Add(dtRow);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
strmReader.Close();
}
}
void Output()
{
string sPrimaParole = string.Empty;
DataRow[] dtFilter = dtTableInput.Select("1=1", "PrimaParole ASC");
DataRow rowI;
// 1° ordinamento in base alla prima parola
for (Int16 n = 0; n < dtFilter.Length; n++)
{
rowI = dtFilter[n];
if (!sPrimaParole.Equals(rowI["PrimaParole"].ToString()))
{
sPrimaParole = rowI["PrimaParole"].ToString();
//
DataRow rowO = dtableOutput.NewRow();
rowO["PrimaParole"] = rowI["PrimaParole"].ToString();
rowO["Riga"] = rowI["Riga"].ToString();
rowO["Count"] = Convert.ToInt16(rowI["Count"]);
dtableOutput.Rows.Add(rowO);
}
}
// costituzione delle nuove righe
for (Int16 n = 0; n < dtFilter.Length; n++)
{
rowI = dtFilter[n];
foreach (DataRow rowO in dtableOutput.Rows)
{
if (!rowO["Riga"].ToString().Equals(rowI["Riga"].ToString()) && rowO["PrimaParole"].ToString().Equals(rowI["PrimaParole"].ToString()))
{
rowO["Riga"] = rowO["Riga"].ToString() + " (" + rowI["Riga"].ToString() + ")";
rowO["Count"] = Convert.ToInt16(rowO["Count"]) + Convert.ToInt16(rowI["Count"]);
}
}
}
// scrittura sul file
FileStream fs = new FileStream("output.txt", FileMode.Create, FileAccess.Write);
StreamWriter strmWriter = new StreamWriter(fs, Encoding.UTF8);
try
{
foreach (DataRow row in dtableOutput.Rows)
strmWriter.WriteLine(row["Riga"].ToString() + ": " + row["Count"].ToString());
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
strmWriter.Close();
}
}
Input();
Output();
Codice: Seleziona tutto
$ cat input.txt
Pippo: 2
Pippo Pluto: 3
Paperino: 1
Topolino Pippo: 4
Pippo Minnie: 1
$ cat output.txt
Paperino: 1
Pippo (Pippo Pluto) (Pippo Minnie): 6
Topolino Pippo: 4
Visualizzano questa sezione: 0 utenti iscritti e 14 ospiti