web-dev-qa-db-fra.com

Comment afficher certaines lignes d'un fichier texte sous Linux?

Je suppose que tout le monde connaît les utilitaires utiles de la ligne cmd de Linux head et tail. head vous permet d'imprimer les X premières lignes d'un fichier, tail fait de même mais imprime la fin du fichier. Qu'est-ce qu'une bonne commande pour imprimer le milieu d'un fichier? quelque chose comme middle --start 10000000 --count 20 (imprimez les 10 000 000 000 à 10 000 000 €).

Je cherche quelque chose qui traitera efficacement les gros fichiers. J'ai essayé tail -n 10000000 | head 10 et c'est horriblement lent.

92
Boaz
sed -n '10000000,10000020p' filename

Vous pourriez peut-être accélérer un peu comme ceci:

sed -n '10000000,10000020p; 10000021q' filename

Dans ces commandes, l'option -n oblige sed à "supprimer l'impression automatique de l'espace de motif". La commande p "imprime [s] l'espace de motif courant" et la commande q "Quitte immédiatement [s] le script sed sans traiter plus d'entrée ..." Les guillemets proviennent de la sedman page .

Au fait, votre commande

tail -n 10000000 filename | head 10

commence à la dix millionième ligne de la fin du fichier, tandis que votre commande "milieu" semble commencer à la dix millionième de la début qui serait équivalent à:

head -n 10000010 filename | tail 10

Le problème est que pour les fichiers non triés avec des lignes de longueur variable, tout processus devra passer par les nouvelles lignes de comptage de fichiers. Il n'y a aucun moyen de raccourcir cela.

Si, cependant, le fichier est trié (un fichier journal avec des horodatages, par exemple) ou a des lignes de longueur fixe, vous pouvez rechercher dans le fichier en fonction d'une position d'octet. Dans l'exemple de fichier journal, vous pouvez effectuer une recherche binaire pour une plage de temps comme le fait mon Python ici *. Dans le cas du fichier à longueur d'enregistrement fixe) , c'est vraiment facile. Vous cherchez simplement linelength * linecount caractères dans le fichier.

* Je continue de vouloir publier une autre mise à jour de ce script. Peut-être que j'y arriverai un de ces jours.

J'ai découvert l'utilisation suivante de sed

sed -n '10000000,+20p'  filename

J'espère que c'est utile à quelqu'un!

29
Dox

C'est la première fois que je publie ici! Quoi qu'il en soit, celui-ci est facile. Supposons que vous souhaitiez extraire la ligne 8872 de votre fichier appelé file.txt. Voici comment procéder:

cat -n fichier.txt | grep '^ * 8872'

Maintenant, la question est de trouver 20 lignes après cela. Pour ce faire, vous devez

cat -n fichier.txt | grep -A 20 '^ * 8872'

Pour les lignes autour ou avant voir les drapeaux -B et -C dans le manuel grep.

4
Dennis

Utilisez la commande suivante pour obtenir la plage particulière de lignes

awk 'NR < 1220974{next}1;NR==1513793{exit}' debug.log | tee -a test.log

Voici debug.log est mon fichier qui se compose d'un manque de lignes et j'ai utilisé pour imprimer les lignes du numéro de ligne 1220974 à 1513793 dans un fichier test.log. espérons qu'il sera utile pour capturer la gamme de lignes.

1
newbie13

La réponse sed de Dennis est la voie à suivre. Mais en utilisant juste la tête et la queue, sous bash:

 middle () {head -n $ [$ 1 + $ 2] | queue -n $ 2; } 

Cela scanne les premières lignes de 1 $ + 2 $ deux fois, c'est donc bien pire que la réponse de Dennis. Mais vous n'avez pas besoin de vous souvenir de toutes ces lettres sed pour l'utiliser ....

1
Charles Stewart

A Ruby version oneliner.

Ruby -pe 'next unless $. > 10000000 && $. < 10000020' < filename.txt

Cela peut être utile à quelqu'un. Les solutions avec "sed" fournies par Dennis et Dox sont très agréables, même parce qu'elles semblent plus rapides.

0
shardan

Perl est roi:

Perl -ne 'print if ($. == 10000000 .. $. == 10000020)' filename
0
Peter V. Mørch

Si vous connaissez les numéros de ligne, dites que vous voulez obtenir les lignes 1, 3 et 5 d'un fichier, dites/etc/passwd:

Perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
0
Dagelf

Vous pouvez utiliser 'nl'.

nl filename | grep <line_num>
0
Ajay

Par exemple, cet awk imprimera des lignes entre 20 et 40

awk '{if ((NR> 20) && (NR <40)) affiche $ 0}'/etc/passwd

0
Hrvoje Špoljar