Comando shell Linux per filtrare un file di testo per lunghezza della linea


19

Ho un'immagine del disco da 30 GB di una partizione borked (pensa dd if=/dev/sda1 of=diskimage) da cui ho bisogno di recuperare alcuni file di testo. Strumenti di intaglio dei dati come foremostfunzionano solo su file con intestazioni ben definite, cioè non file di testo semplice, quindi sono tornato sul mio buon amico strings.

strings diskimage > diskstrings.txt prodotto un file di testo da 3 GB contenente un sacco di stringhe, per lo più cose inutili, mescolate con il testo che in realtà voglio.

La maggior parte dell'innesto tende ad essere stringhe davvero lunghe e ininterrotte di incomprensioni. Le cose che mi interessano sono garantite per essere inferiori a 16kb, quindi ho intenzione di filtrare il file per lunghezza della linea. Ecco lo script Python che sto usando per farlo:

infile  = open ("infile.txt" ,"r");
outfile = open ("outfile.txt","w");
for line in infile:
    if len(line) < 16384:
        outfile.write(line)
infile.close()
outfile.close()

Funziona, ma per riferimento futuro: ci sono magici incantesimi di una riga (pensa awk, sed) che filtrerebbero un file per lunghezza della linea?

Risposte:


28
awk '{ if (length($0) < 16384) print }' yourfile >your_output_file.txt

stamperebbe linee più corte di 16 kilobyte, come nel tuo esempio.

O se ti piace Perl:

perl -nle 'if (length($_) < 16384) { print }' yourfile >your_output_file.txt

Bene, è stato imbarazzantemente semplice. Grazie. :)
Li-aung Yip

Aggiunta anche la versione Perl :-)
Janne Pikkarainen il

E lo script awk può essere scritto come awk 'length($0) < 16384' file > output, poiché l'azione predefinita è stampare la linea.
Glenn Jackman,

8

Questo è simile alla risposta di Ansgar, ma leggermente più veloce nei miei test:

awk 'length($0) < 16384' infile >outfile

È la stessa velocità delle risposte di altri awk. Si basa sull'implicito printdi una vera espressione, ma non ha bisogno di prendere il tempo per dividere la linea come fa Ansgar.

Nota che AWK ti offre un servizio ifgratuito. Il comando sopra è equivalente a:

awk 'length($0) < 16384 {print}' infile >outfile

Non esiste un esplicito if(o il suo circostante set di parentesi graffe) come in alcune delle altre risposte.

Ecco un modo per farlo in sed:

sed '/.\{16384\}/d' infile >outfile

o:

sed -r '/.{16384}/d' infile >outfile

che eliminano qualsiasi riga contenente 16384 (o più) caratteri.

Per completezza, ecco come utilizzare sedper salvare le righe più lunghe della soglia:

sed '/^.\{0,16383\}$/d' infile >outfile

2

Puoi awkcome:

$ awk '{ if (length($0) < 16384) { print } }' /path/to/text/file

Questo stamperà le righe più lunghe di 16K caratteri (16 * 1024).

Puoi usare grepanche:

$ grep ".\{,16384\}" /path/to/text/file

Questo stamperà le righe al massimo 16K caratteri.


Non sono sicuro che grepsia una buona idea - è una regexp semplice, certo, ma più computazionalmente costosa di awk. "Un uomo con problemi dice" Userò espressioni regolari! "Ora ha due problemi." ;)
Li-aung Yip,

È solo un altro modo di farlo. La prima opzione che ho pubblicato stava usando awk.
Khaled

1
+1 per la regexp, perché gioca a golf meglio e non mi fa leggere awk manpages =)
Ciro Santilli 12 改造 中心 法轮功 六四 事件

2

Non molto diverso dalle risposte già fornite, ma ancora più breve:

awk -F '' 'NF < 16384' infile >outfile
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.