web-dev-qa-db-fra.com

Commande de shell Linux pour filtrer un fichier texte par longueur de ligne

J'ai une image de disque de 30 Go d'une partition bouchée (pense dd if=/dev/sda1 of=diskimage) que j'ai besoin de récupérer certains fichiers texte de. Les outils de sculpture de données tels que foremost ne fonctionnent que sur des fichiers avec des en-têtes bien définis, c'est-à-dire des fichiers texte simples, donc je suis tombé sur mon bon ami strings.

strings diskimage > diskstrings.txt Produit un fichier texte de 3 Go contenant une bouquet de chaînes, principalement des objets inutiles, mélangés au texte que je veux réellement.

La majeure partie de la cruft a tendance à être vraiment longues, des cordes ininterrompues de gibberish. Le contenu que je suis intéressé est garanti d'être inférieur à 16 Ko, alors je vais filtrer le fichier par longueur de ligne. Voici le Python script que j'utilise pour le faire:

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()

Cela fonctionne, mais pour une référence future: y a-t-il des incantations magiques d'une ligne (pensez awk, sed) qui filtrerait un fichier par ligne de ligne?

19
Li-aung Yip
awk '{ if (length($0) < 16384) print }' yourfile >your_output_file.txt

imprimerait des lignes plus courtes que 16 kilo-octets, comme dans votre propre exemple.

Ou si vous avez envie de Perl:

Perl -nle 'if (length($_) < 16384) { print }' yourfile >your_output_file.txt
28
Janne Pikkarainen

Ceci est similaire à la réponse d'Ansgar, mais légèrement plus rapide dans mes tests:

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

C'est la même vitesse que les autres réponses AWK. Il repose sur l'implicite print d'une véritable expression, mais n'a pas besoin de prendre le temps de diviser la ligne d'ANSGAR.

Notez que AWK vous donne un if gratuitement. La commande ci-dessus est équivalente à:

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

Il n'y a pas de if (ou son ensemble d'accolades bouclés) comme dans certaines des autres réponses.

Voici un moyen de le faire dans sed:

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

ou:

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

qui suppriment une ligne contenant 16384 caractères (ou plus).

Pour complétude, voici comment vous utiliseriez sed pour enregistrer des lignes plus longtemps que votre seuil:

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

Pas vraiment différent des réponses déjà données, mais plus courte encore:

awk -F '' 'NF < 16384' infile >outfile
2
Ansgar Esztermann

Vous pouvez awk tel que:

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

Cela imprimera les lignes plus courtes que 16k caractères (16 * 1024).

Vous pouvez utiliser grep aussi:

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

Cela imprimera les lignes au plus de caractères 16k.

2
Khaled