web-dev-qa-db-fra.com

Comment grep des lignes, basées sur un certain motif?

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 

Je n'ai besoin que de la ligne contenant le motif /aa/bbbb/cccccc, 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 ligne complète pour que grep -o ne puisse 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?

8
heemayl

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 indique que le caractère qui précède la chaîne /aa/bbbb/cccccc serait n'importe quel caractère, mais pas un caractère non-espace.

  • (?!\S) Le préfixe négatif affirme que le caractère suivant la correspondance serait n'importe quel caractère mais pas un caractère non-espace.

Un autre grep,

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

En 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 ainsi: script.py. Puis exécutez le script ci-dessus en

python3 script.py /path/to/the/file/you/want/to/work/with
7
Avinash Raj

Le moyen le plus simple serait d'ajouter un espace après votre modèle:

$ 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 également correspondre les lignes qui ne contiennent que votre modèle (aucun espace 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 champ 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
    
10
terdon

Pour compléter @ AvinashRajréponse , vous pouvez également utiliser une commande comme celle-ci.

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