93 votes

Obtenir la dernière correspondance dans un fichier en utilisant grep

Quelle est la meilleure façon d'obtenir uniquement la dernière correspondance d'une expression régulière dans un fichier en utilisant grep ?

De plus, est-il possible de commencer la recherche à partir de la fin du fichier au lieu du début et de l'arrêter lorsqu'elle trouve la première correspondance ?

139voto

Cakemox Points 23637

Vous pouvez essayer

grep pattern file | tail -1

ou

tac file | grep pattern | head -1

ou

tac file | grep -m1 pattern

31 votes

tac file | grep -m 1 pattern

1 votes

Avec la contrainte supplémentaire que je voulais obtenir le numéro de ligne ( grep -n ) dans le fichier actuel, je pense tac devait être évitée, à moins que je ne veuille faire des soustractions avec des wc -l . Autrement tac avec grep -m1 a beaucoup de sens.

1 votes

I

2voto

Ismail Guneydas Points 134

J'utilise toujours le chat (mais cela rend le chemin un peu plus long) : cat file | grep pattern | tail -1

Je blâmerais mon professeur de cours d'administration linux à l'université qui adore les chats :))))

-- Vous n'avez pas besoin de catcher un fichier avant de le greffer. grep pattern file | tail -1 et est aussi plus efficace.

6 votes

Il s'agit de la première partie de la réponse de Cakemox, mais en pire.

1 votes

Cela fonctionne, mais il y a des étapes inutiles. Pour un usage léger, cette solution fonctionne bien, mais elle n'est pas très performante. La raison en est que vous n'avez pas besoin de cat le fichier et l'acheminer vers grep . Vous pouvez avoir grep rechercher le fichier directement via grep pattern file (et utiliser ensuite tail pour renvoyer le dernier résultat), comme dans la réponse de Cakemox.

2voto

biocyberman Points 243

Pour quelqu'un qui travaille avec d'énormes fichiers texte sous Unix/Linux/Mac/Cygwin. Si vous utilisez Windows, consultez cette page sur les outils Linux dans Windows : https://stackoverflow.com/questions/3519738/what-is-the-best-way-to-use-linux-utilities-under-Windows .

On peut suivre ce flux de travail pour avoir de bonnes performances :

  1. compresser avec gzip
  2. utiliser zindex (sur github : https://github.com/mattgodbolt/zindex ) pour indexer le fichier avec clé appropriée
  3. interroger le fichier indexé avec zq du paquet.

Citation de son readme github :

Création d'un index

zindex a besoin de savoir quelle partie de chaque ligne constitue l'index. Cela peut être fait par une expression régulière, par champ, ou en faisant passer chaque ligne par un programme externe. ligne à travers un programme externe.

Par défaut, zindex crée un index de fichier.gz.zindex lorsqu'on lui demande d'indexer un fichier.gz. indexer le fichier .gz.

Ejemplo:

créer un index sur les lignes correspondant à une régularité numérique numérique régulière. Le groupe de capture indique la partie qui doit être indexée, et les options montrent que chaque ligne a un index numérique unique.

$ zindex file.gz --regex 'id:([0-9]+)' --numeric --unique

Exemple : créer un index sur le deuxième champ d'un fichier CSV :

$ zindex file.gz --delimiter , --field 2 

Ejemplo:

créer un index sur un champ JSON orderId.id dans n'importe quel élément de la racine du document. actions de la racine du document (nécessite jq). La requête jq crée un tableau de tous les champs orderId.ids, puis les joint avec un espace pour s'assurer que chaque ligne individuelle ligne individuelle envoyée à jq crée une seule ligne de sortie, avec des correspondances multiples séparées par des espaces (ce qui est le cas pour la requête jq). séparées par des espaces (qui est le séparateur par défaut).

$ zindex file.gz --pipe "jq --raw-output --unbuffered '[.actions[].orderId.id] | join(\" \")'" 

Interroger l'index

Le programme zq est utilisé pour interroger un index. On lui donne le nom de l'index fichier compressé et une liste de requêtes. Par exemple :

$ zq file.gz 1023 4443 554 

Il est également possible d'effectuer une sortie par ligne afin d'imprimer les lignes 1 et 1000 d'un fichier :

$ zq file.gz --line 1 1000

1voto

zyy Points 101

Les solutions ci-dessus ne fonctionnent que pour un seul fichier, pour imprimer la dernière occurrence de plusieurs fichiers (dire avec le suffixe .txt ), utilisez le bash script suivant

#!/bin/bash
for fn in `ls *.txt`
do
    result=`grep 'pattern' $fn | tail -n 1`
echo $result
done

'pattern' est ce que vous souhaitez grep.

0voto

MartinB Points 1

Si vous avez plusieurs fichiers, utilisez inline-for :

for a in *.txt; do grep "pattern" $a /dev/null | tail -n 1; done

Le fichier /dev/null fournit un deuxième fichier, de sorte que grep énumère le nom du fichier dans lequel le motif a été trouvé.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X