Script per formattare un file di testo

di il
1 risposte

Script per formattare un file di testo

Ciao a tutti,

Sto usando Awk per processare 2 file di testo in modo da crearne un terzo opportunatamente formattato sulla base di stringhe in comune (poi vi spiego)
Vi spiego l' impasse in cui sono finito.

I 2 file di testo li chiamo g1.txt e g2.txt. Il primo, g1, ha questo contenuto:
alfa beta;www.google.com
Light Dweller - CR, Technical Metal;http://alfa.org;http://beta.org;http://gamma.org;
il secondo, g2, contiene, invece, questo testo
Jack to ride.zip;http://alfa.org;
JKr.rui.rar;http://gamma.org;
Nofj ogk.png;http://gamma.org;
Ora, io uso uno script per produrre il terzo file, g3.txt, formattato in questo modo
alfa beta;www.google.com
Light Dweller - CR, Technical Metal;http://alfa.org;http://beta.org;http://gamma.org;;Jack to ride.zip;JKr.rui.rar;Nofj ogk.png
Prima di mostrarvi il codice, vi spiego il perchè di questo output: sia nel file g1.txt e sia nel file g2.txt potete vedere delle stringhe in comune. Ad esempio, potete vedere che la stringa racchiusa dal separatore ;
http://gamma.org
è presente in entrambi i file di testo. Nel caso di g1.txt questa stringa si trova alla seconda riga mentre in g2.txt la stessa stringa si trova sia sulla seconda nonchè sulla terza riga.

Il file g3.txt che cos'ha di particolare?

- le righe aventi le stringhe in comune sono raggruppate su un'unica riga e solo su una unica riga in tutto il file di testo. Quindi, la stringa
http://gamma.org
sarà presente una volta sola, non potrà trovarsi su una riga diversa.
- i doppioni vengono rimossi, ad esempio la stringa
http://gamma.org
viene visualizzata una volta sola sulla stessa riga, in altre parole non possiamo avere qualcosa di simile
http://gamma.org;JKr.rui.rar;http://gamma.org
perchè la stringa si ripete.

Allora, tutto questo lo faccio con questi 2 codici

unisci.awk
BEGIN {
  OFS=FS=";"
}
ARGIND == 1 {
   map[$2] = ($2 in map ? map[$2] OFS : "") $1
   next
}
{
   r = $0;
   for (i=1; i<=NF; ++i)
      if ($i in map)
         r = r OFS map[$i]
   $0 = r
}
1

e unisci.sh
#! /usr/bin/awk  -f

BEGIN {
  OFS=FS=";"
  C=0;
}
{
  if (ARGIND == 1) {
     X = $NF
     T0[$NF] = C++
     $NF = ""
     if (T1[X]) {
        T1[X] = T1[X] $0
     } else {
        T1[X] = $0
     }
  } else {
     X = $NF
     T0[$NF] = C++
     $NF = ""
     if (T2[X]) {
        T2[X] = T2[X] $0
     } else {
        T2[X] = $0
     }
  }
}

END {
  for (X in T0) {
    # concatenate T1[X] and X, since T1[X] ends with ";"
    print T1[X]  X, T2[X]
  }
}
Lo utilizzo in questo modo
awk -f unisci.awk g2.txt g1.txt
La ragione per cui ne ho 2 di codici (il primo si chiama unisci.awk e il secondo unisci.sh) è perchè altrimenti non mi verrebbe conservato l'ordine delle righe, cioè, eseguendo lo script mi viene fuori un output di questo genere
Light Dweller - CR, Technical Metal;http://alfa.org;http://beta.org;http://gamma.org;;Jack to ride.zip;JKr.rui.rar;Nofj ogk.png
alfa beta;www.google.com
Ma il file g1.txt ha prima la riga alfa beta.

Qual è il mio problema? Che lo script non mi funziona se ho questo testo nei 2 file di testo g1.txt e g2.txt

g1.txt
alfa beta;https://123.org/a/in.ph?shw=297585;
Light Dweller;https://123.org/a/in.ph?shw=3869;
Imp - Alp;https://123.org/a/in.ph?shw=340249;
g2.txt
Link;1996 7.zip;https://yd.k/d/BbNUb-2yhVmVnw;https://123.org/a/in.ph?shw=3869;https://123.org/a/in.ph?shw=3869&st=30;
Link;Moonblo (Tape)_123.zip;https://yd.k/d/57i;https://123.org/a/in.ph?shw=3869&st=30;
Link;Moonblo(Demo) [1996].rar;https://yd.k/d/A7U;https://123.org/a/in.ph?shw=3869;
L'output g3.txt che erroneamente mi produce è questo
alfa beta;https://123.org/a/in.ph?shw=297585;;;
Light Dweller;https://123.org/a/in.ph?shw=3869;;;
Imp - Alp;https://123.org/a/in.ph?shw=340249;;;
ma l'output che io mi aspetto che venga fuori dovrebbe essere invece
alfa beta;https://123.org/a/in.ph?shw=297585;
Light Dweller;https://123.org/a/in.ph?shw=3869;Link;1996 7.zip;https://yd.k/d/BbNUb-2yhVmVnw;https://123.org/a/in.ph?shw=3869&st=30;Link;Moonblo(Demo) [1996].rar;https://yd.k/d/A7U;
Imp - Alp;https://123.org/a/in.ph?shw=340249;

1 Risposte

  • Re: Script per formattare un file di testo

    Dopo molti tentativi finalmente ho trovato una soluzione
    BEGIN{FS=OFS=";"}
    {sub(/;$/,"")}
    NR==FNR{
        for (i=1;i<=NF;++i)
            for (j=1;j<=NF;++j)
                if (j!=i&&!b[$i,$j]++)
                    a[$i,++c[$i]]=$j
        next
    }
    {
        delete b
        for (i=1;i<=NF;++i)
            ++b[$i]
        for (i=1;i<=NF;++i)
            for (j=1;j<=c[$i];++j)
                if (!b[a[$i,j]]++)
                    $(NF+1)=a[$i,j]
        print
    }
    usando in questo modo
    awk -f script.awk 2.txt 1.txt
    Ho dovuto cambiare il testo

    1.txt
    UU;    
    AA;BB;
    ZZ;KK;
    2.txt
    CC;DD;BB;AA;
    LL;KK;
    GH;ZZ;SS;
    l'output corretto che viene generato è questo



    Sostanzialmente questo script mi serviva per risolvere un problema legato all'individuazione del corretto nome degli archivi quando li andavo a scaricare. Dato che i nomi di questi erano anche molto strani, ad esempio rhkF.rar, avevo bisogno di risalire al nome della pagina web in cui quell'indirizzo url si trovava e quindi, andando ad estrarre il testo dal relativo tag <title> potevo finalmente fare un'associazione del tipo
    La logica delle scoperte scientifiche;rhkF.rar
    Andando a scaricare l'archivio rhkF.rar potevo sapere che in realtà si chiamava La logica delle scoperte scientifiche.
    Ovviamente non potevo trascrivere manualmente uno ad uno gli archivi scaricati con i relativi nomi visto che il numero degli archivi da scaricare era molto alto
Devi accedere o registrarti per scrivere nel forum
1 risposte