Split: come suddividere in diverse percentuali?


14

Come posso dividere un file di testo in 70% e 30% usando il comando dividi?


Sei obbligato a usare il comando split? Altrimenti, puoi farlo facilmente con una semplice manipolazione del testo, usando certamente perl o python. Finché il file non è troppo sbagliato, leggilo in memoria come una stringa, quindi dividi la stringa. Se il file è troppo grande, è necessario ulteriore lavoro.
Faheem Mitha,

@Faheem Mitha Il file è 64 MB. Mi piace l'idea di usare split perché è più veloce della scrittura del codice. Ora mi chiedevo se specificassi il numero di righe corrispondenti al 70% del file, ottengo un file grande e un file piccolo. Non dovrebbe funzionare?
aneuryzm,

E sì .. ha funzionato .. Devo eliminare la domanda?
aneuryzm,

A te, ma non necessario.
Faheem Mitha,

Per favore, condividi la tua risposta. ( meta.stackexchange.com/questions/12513/… )
dogbane

Risposte:


13

I comandi seguenti funzionano con percentuali superiori al 50% (se si desidera dividere solo in due file), approccio rapido e sporco.

1) dividere il 70% in base alle linee

split -l $[ $(wc -l filename|cut -d" " -f1) * 70 / 100 ] filename 

2) dividere il 70% in base ai byte

split -b $[ $(wc -c filename|cut -d" " -f1) * 70 / 100 ] filename

1
Su MacOSX a volte restituisce il numero di righe con uno spazio davanti, qualcosa che rompe questo script. La prima connessione a xargs rimuoverà quegli spazi e farà funzionare di nuovo le cose: split -l $[ $(wc -l filename | xargs | cut -d" " -f1) * 70 / 100 ] filename
Emil Stenström,

4

Puoi usare csplitper dividere in due pezzi (usando qualsiasi percentuale) ad esempio primo pezzo - primo 20% di linee, secondo pezzo - il restante 80% di linee:

csplit infile $(( $(wc -l < infile) * 2 / 10 + 1))

$(wc -l < infile): numero totale di righe
2 / 10: percentuale
+1: aggiungi una riga perché si csplitdivideup to but not including line N

Tuttavia, puoi dividere solo in base alle linee.
Fondamentalmente, fintanto che hai il numero di linea tramite $(( $(wc -l < file) * 2 / 10))puoi usare qualsiasi strumento orientato alla linea:

sed 1,$(( $(wc -l < infile) * 2 / 10))'{
w 20-infile
d
}' infile > 80-infile

o anche più fresco:

{ head -n$(( $(wc -l < infile) * 2 / 10)) > 20-infile; cat > 80-infile; } <infile

anche se alcuni headsono stupidi e non conformi agli standard, quindi non funzionerà su tutte le configurazioni ...


2
{   BS=$(($(wc -c <file) * $P / 100))
    dd count=1 bs="$BS" >file1; cat
} <file >file2 2>/dev/null

... dovrebbe funzionare per questo semplice caso perché ti dividi solo una volta - e quindi probabilmente splitè un po 'eccessivo. Fino a quando il file è ricercabile, ddservirà solo a fare una sola read()su <stdin, e così catè lasciato per iniziare la sua read()in qualsiasi punto ddlascia.

Se il file è grande, allora count=1 bs=$big_ol_numpotrebbe diventare un po 'ingombrante e può essere bloccato con un po' di matematica in più - ma semplice - shell.

Un ingresso non seekable - come da un tubo - potrebbe inclinare dd's risultati, anche se questo può essere gestito così w / GNU dd' s iflag=fullblock.


0

Il seguente codice utilizza heade tailfunziona con qualsiasi rapporto (da 40 a 60 in questo caso):

export FILE_NAME=train.vw
head -n $[ $(wc -l ${FILE_NAME}|cut -d" " -f1) * 40 / 100 ] ${FILE_NAME} > train_40.vw
tail -n +$[ ($(wc -l ${FILE_NAME}|cut -d" " -f1) * 40 / 100) + 1 ] ${FILE_NAME} > train_60.vw
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.