Successivo: , Precedente: , Su: Cloni   [Contenuti][Indice]


11.2.4 Suddividere in pezzi un file grosso

Il programma split divide grossi file di testo in pezzi più piccoli. La sua sintassi è la seguente:81

split [-contatore] [file] [prefisso]

Per default, i file di output avranno nome xaa, xab, e così via. Ogni file contiene 1.000 righe, con la probabile eccezione dell’ultimo file. Per cambiare il numero di righe in ogni file, va indicato un numero sulla riga di comando, preceduto da un segno meno (p.es., ‘-500’ per file con 500 righe ognuno invece che 1.000). Per modificare i nomi dei file di output in qualcosa del tipo miofileaa, miofileab, e così via, va indicato un argomento ulteriore che specifica il prefisso del nome-file.

Ecco una versione di split in awk. Usa le funzioni ord() e chr() descritte nella Tradurre tra caratteri e numeri.

Il programma dapprima imposta i suoi valori di default, e poi controlla che non siano stati specificati troppi argomenti. Quindi esamina gli argomenti uno alla volta. Il primo argomento potrebbe essere un segno meno seguito da un numero. Poiché il numero in questione può apparire negativo, lo si fa diventare positivo, e viene usato per contare le righe. Il nome del file-dati è per ora ignorato e l’ultimo argomento è usato come prefisso per i nomi-file in output:

# split.awk --- comando split scritto in awk
#
# Richiede le funzioni di libreria ord() e chr()
# sintassi: split [-contatore] [file] [nome_in_output]

BEGIN {
    outfile = "x"    # default
    contatore = 1000
    if (ARGC > 4)
        sintassi()

    i = 1
    if (i in ARGV && ARGV[i] ~ /^-[[:digit:]]+$/) {
        contatore = -ARGV[i]
        ARGV[i] = ""
        i++
    }
    # testa argv nel caso che si legga da stdin invece che da file
    if (i in ARGV)
        i++    # salta nome file-dati
    if (i in ARGV) {
        outfile = ARGV[i]
        ARGV[i] = ""
    }
    s1 = s2 = "a"
    out = (outfile s1 s2)
}

La regola seguente fa il grosso del lavoro. contatore_t (contatore temporaneo) tiene conto di quante righe sono state stampate sul file di output finora. Se questo numero supera il valore di contatore, è ora di chiudere il file corrente e di iniziare a scriverne uno nuovo. Le variabili s1 e s2 sono usate per creare i suffissi da apporre a nome-file. Se entrambi arrivano al valore ‘z’, il file è troppo grosso. Altrimenti, s1 passa alla successiva lettera dell’alfabeto e s2 ricomincia da ‘a’:

{
    if (++contatore_t > contatore) {
        close(out)
        if (s2 == "z") {
            if (s1 == "z") {
                printf("split: %s è troppo grosso da suddividere\n",
                       nome_file) > "/dev/stderr"
                exit 1
            }
            s1 = chr(ord(s1) + 1)
            s2 = "a"
        }
        else
            s2 = chr(ord(s2) + 1)
        out = (outfile s1 s2)
        contatore_t = 1
    }
    print > out
}

La funzione sintassi() stampa solo un messaggio di errore ed esce:

function sintassi()
{
    print("sintassi: split [-num] [file] [nome_in_output]") > "/dev/stderr"
    exit 1
}

Questo programma è un po’ approssimativo; conta sul fatto che awk chiuda automaticamente l’ultimo file invece di farlo in una regola END. Un altro presupposto del programma è che le lettere dell’alfabeto siano in posizioni consecutive nella codifica in uso, il che non è vero per i sistemi che usano la codifica EBCDIC.


Note a piè di pagina

(81)

Questo è la sintassi tradizionale. La versione POSIX del comando ha una sintassi differente, ma per lo scopo di questo programma awk la cosa non ha importanza.


Successivo: , Precedente: , Su: Cloni   [Contenuti][Indice]