J'ai un fichier contenant environ 10 millions de lignes.
Je souhaite supprimer toutes les lignes du fichier contenant moins de six caractères.
Comment puis-je faire cela?
command-line
text-processing
Dis moi pourquoi
la source
la source
Réponses:
Il y a plusieurs façons de procéder.
En utilisant
grep
:Contiendra désormais
out.txt
des lignes de six caractères ou plus.Inverse:
Utilisation
sed
, suppression de lignes de longueur 5 ou moins:Inverser, imprimer des lignes de longueur six ou plus:
Vous pouvez enregistrer la sortie dans un fichier différent en utilisant l'
>
opérateur commegrep
ou modifier le fichier sur place en utilisant l'-i
option desed
:Le fichier d'origine sera sauvegardé en tant que
file.txt.bak
et le fichier modifié serafile.txt
.Si vous ne souhaitez pas conserver de sauvegarde:
Utiliser shell, Slower, Don't do this , c'est juste pour montrer une autre méthode:
L' utilisation
python
, encore plus lent quegrep
,sed
:Mieux utiliser la compréhension des listes pour être plus Pythonic:
la source
C'est très simple:
Ceci est extrêmement efficace, car
grep
il n'essaiera pas d'analyser plus que ce dont il a besoin, ni d'interpréter les caractères de quelque manière que ce soit: il envoie simplement une ligne (entière) à stdout (que le shell redirige ensuite vers le fichier de résultats) dès qu'il a vu 6 les caractères sur cette ligne (.
dans un contexte d'expression régulière correspond à n'importe quel caractère).Ainsi, grep ne sortira que les lignes ayant 6 (ou plus) caractères, et les autres ne sont pas sorties par grep, donc elles ne parviennent pas au fichier de résultats.
la source
Solution n ° 1: utiliser C
Méthode la plus rapide: compilez et exécutez ce programme C:
Compilez avec
gcc program.c -o program
, exécutez avec./program file line_length
(oùfile
= chemin d'accès au fichier etline_length
= longueur de ligne minimale, dans votre cas6
; la longueur de ligne maximale est limitée à des1000000
caractères par ligne; vous pouvez modifier cela en modifiant la valeur deMAX_BUFFER_SIZE
).(Astuce pour remplacer
\n
par\0
trouvé ici .)Comparaison avec toutes les autres solutions proposées à cette question à l'exception de la solution shell (test exécuté sur un fichier ~ 91MB avec 10M lignes avec une longueur moyenne de 8 caractères):
Solution n ° 2: en utilisant AWK:
length>=6
: silength>=6
renvoie VRAI, imprime l'enregistrement en cours.Solution n ° 3: utiliser Perl:
lenght>=6
renvoie VRAI, imprime l'enregistrement en cours.la source
awk
solution ..sed
solution (ça arrive, je sais). XDpos
variable? Je comprends qu'il retourne un pointeur sur le caractèreline
avec un caractère de nouvelle ligne, mais vous ne semblez jamais l'utiliser. Et si vous ne le trouvez pas, vous le définissez simplement égal à\0
.\0
(strchr()
renvoie un pointeur NULL si le caractère n'est pas trouvé). Le point consiste à remplacer chaque nouvelle ligne à la fin de chaque ligne par\0
afin que la nouvelle ligne ne soit jamais comptée parstrlen()
: c'est pour que la longueur puisse toujours être comparée à 6, indépendamment d'une nouvelle ligne potentiellement manquante sur la dernière ligne. Traiter différemment seule la dernière ligne serait beaucoup plus efficace, je sais. Je mettrai probablement cela à jour plus tard.grep
solution sur le même fichier et c'est en fait plus rapide (probablement parce que cestrlen()
n'est pas la meilleure idée ici) . Je vais essayer d'utiliser unegetchar()
boucle afin de ne vérifier que le premier caractère N à la place, je suppose que cela devrait l'améliorer visiblement. Et oui, toute ligne au-dessus de la longueur du tampon est simplement coupée à la longueur du tampon.Vous pouvez utiliser Vim en mode Ex:
\v
allume la magie.{6}
rechercher des lignes avec 6 caractères ou plusv
inverser la sélectiond
supprimerx
sauver et fermerla source
Solution Ruby:
Idée simple: rediriger le fichier vers stdin de ruby et imprimer la ligne depuis stdin uniquement si sa longueur est supérieure ou égale à 6
la source