Comment grep les lignes, sur la base d'un certain modèle?

8

Disons que j'ai un fichier contenant les deux lignes suivantes:

2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
2014-05-05      09:12:17    /aa/bbbb/cccccc?dddddddd    16767 

J'ai besoin d'obtenir la ligne contenant /aa/bbbb/ccccccuniquement le motif , je n'ai pas besoin de la deuxième ligne contenant des caractères supplémentaires, c'est-à-dire ?dddddddd. Maintenant, quand j'ai essayé

grep '/aa/bbbb/cccccc' file

Ensuite, les deux lignes sélectionnées. J'ai besoin de la gamme complète, donc grep -oje ne pourrais pas être une solution.

Quelle pourrait être la solution possible en utilisant grep afin que seule la première ligne soit sélectionnée en fonction du modèle de recherche?

heemayl
la source

Réponses:

7

Essayez la commande grep ci-dessous qui utilise le paramètre -P( Perl-regexp ).

grep -P '(?<!\S)/aa/bbbb/cccccc(?!\S)' file
  • (?<!\S)Ce regard négatif affirme que le caractère qui précède la chaîne /aa/bbbb/ccccccserait n'importe quel caractère, mais pas un espace.

  • (?!\S) La recherche d'anticipation négative affirme que le caractère suivant la correspondance serait n'importe quel caractère, mais pas un espace.

Un autre grep,

 grep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file

Grâce à python,

script.py

#!/usr/bin/python3
import re
import sys
file = sys.argv[1]
with open(file, 'r') as f:
    for line in f:
        for i in line.split():
            if i == "/aa/bbbb/cccccc":
                print(line, end='')

Enregistrez le code ci-dessus dans un fichier et nommez-le comme script.py. Exécutez ensuite le script ci-dessus en

python3 script.py /path/to/the/file/you/want/to/work/with
Avinash Raj
la source
Merci mec. Btw cela peut-il être fait en utilisant des expressions régulières normales / étendues plutôt que des expressions régulières perl?
heemayl
1
comme terdon a posté, vous pouvez simplementgrep '/aa/bbbb/cccccc ' file
Avinash Raj
Mais ce qui précède n'imprimera pas les lignes qui n'ont que de la /aa/bbbb/ccccccchaîne.
Avinash Raj
Vous pouvez également faire correspondre cela avecgrep -E '/aa/bbbb/cccccc(\s+|$)' file
terdon
oui, comme çagrep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file
Avinash Raj
10

La façon la plus simple serait d'ajouter un espace après votre motif:

$ grep '/aa/bbbb/cccccc ' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou, pour correspondre à toutes sortes d'espaces:

$ grep  '/aa/bbbb/cccccc[[:space:]]' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou

$ grep -P '/aa/bbbb/cccccc\s+' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou, avec un lookahead positif :

$ grep -P '/aa/bbbb/cccccc(?=\s)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou, avec un lookahead négatif :

$ grep -P '/aa/bbbb/cccccc(?!\S)' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou vous pouvez inverser le match:

$ grep  -v 'c?' file
2014-05-05      09:11:53    /aa/bbbb/cccccc             29899

Ou, pour faire correspondre des lignes qui ne contiennent que votre motif (pas d'espace blanc de fin):

grep -P '/aa/bbbb/cccccc(\s+|$)' file 
grep -E '/aa/bbbb/cccccc(\s+|$)' file 

Ou, vous pouvez simplement utiliser un petit script:

  • En awk:

    $ awk '$3=="/aa/bbbb/cccccc"' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    

    Ou, si vous ne savez pas dans quel domaine se trouve votre modèle

    $ awk '{for(i=1;i<=NF;i++){if($i=="/aa/bbbb/cccccc"){print}}}' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
  • En Perl

    $ perl -ane 'print if grep {$_ eq "/aa/bbbb/cccccc"} @F' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    
terdon
la source
@terdon grep -v 'c?' fileexplique pourquoi vous ne l'utilisez pas grep -v '?' filecar le fichier ne contient que deux lignes.
αғsнιη
@KasiyA vrai, je voulais juste garder un peu le schéma. Vous avez tout à fait raison, dans ce cas particulier, ce grep -v '?'serait suffisant.
terdon
2

Pour compléter la réponse de @AvinashRaj , vous pouvez également utiliser une commande comme celle-ci.

grep -P '/a+/b+/c+(?!\S)' file
αғsнιη
la source