Wie grep ich Linien nach einem bestimmten Muster?


8

Angenommen, ich habe eine Datei mit den folgenden zwei Zeilen:

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

Ich brauche nur die Zeile mit dem Muster /aa/bbbb/cccccc, ich brauche nicht die zweite Zeile mit zusätzlichen Zeichen, dh ?dddddddd. Jetzt, als ich es versuchte

grep '/aa/bbbb/cccccc' file

Dann werden beide Zeilen ausgewählt. Ich brauche die volle Linie, grep -okönnte also keine Lösung sein.

Was könnte die mögliche Lösung mit grep sein, damit nur die erste Zeile basierend auf dem Suchmuster ausgewählt wird?

Antworten:


7

Versuchen Sie den folgenden Befehl grep, der den Parameter -P( Perl-regexp ) verwendet.

grep -P '(?<!\S)/aa/bbbb/cccccc(?!\S)' file
  • (?<!\S)Dieser negative Lookbehind behauptet, dass das Zeichen, das der Zeichenfolge vorausgeht /aa/bbbb/cccccc, ein beliebiges, aber kein Leerzeichen ist.

  • (?!\S) Ein negativer Lookahead behauptet, dass das Zeichen nach dem Match ein beliebiges, aber kein Leerzeichen ist.

Noch ein grep,

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

Durch 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='')

Speichern Sie den obigen Code in einer Datei und benennen Sie ihn als script.py. Führen Sie dann das obige Skript mit aus

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

Danke, Mann. Übrigens kann dies mit normalem / erweitertem Regex anstelle von Perl-Regex erfolgen?
Heemayl

1
Wie Terdon geschrieben hat, könnte man einfachgrep '/aa/bbbb/cccccc ' file
Avinash Raj

Die obigen Angaben drucken jedoch nicht die Zeilen, die nur eine /aa/bbbb/ccccccZeichenfolge enthalten.
Avinash Raj

Sie können das auch mitgrep -E '/aa/bbbb/cccccc(\s+|$)' file
terdon

Ja, sogrep -E '(^|\s)/aa/bbbb/cccccc(\s|$)' file
Avinash Raj

10

Am einfachsten ist es, nach dem Muster ein Leerzeichen einzufügen:

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

Oder, um alle Arten von Leerzeichen abzugleichen:

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

Oder

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

Oder mit einem positiven Lookahead :

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

Oder mit einem negativen Lookahead :

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

Oder Sie können das Spiel umkehren:

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

Oder um auch Linien abzugleichen, die nur Ihr Muster enthalten (kein nachfolgendes Leerzeichen):

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

Oder Sie können einfach ein kleines Skript verwenden:

  • In awk:

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

    Oder wenn Sie nicht wissen, in welchem ​​Feld sich Ihr Muster befindet

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

    $ perl -ane 'print if grep {$_ eq "/aa/bbbb/cccccc"} @F' file
    2014-05-05      09:11:53    /aa/bbbb/cccccc             29899
    

@terdon, grep -v 'c?' filewarum Sie nicht verwenden, grep -v '?' fileweil die Datei nur zwei Zeilen enthält.
αғsнιη

@ KasiyA stimmt, ich wollte nur ein bisschen vom Muster behalten. Sie haben jedoch recht, in diesem speziellen Fall grep -v '?'wäre es genug.
Terdon

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.