2009-12-17 11 views
45

Ho bisogno di un modo di cercare un file usando grep tramite un'espressione regolare dalla riga di comando Unix. Per esempio, quando si digita nella riga di comando:Grep e Python

python pythonfile.py 'RE' 'file-to-be-searched' 

Ho bisogno l'espressione regolare 'RE' da ricercare nel file e stampare le linee corrispondenti.

Ecco il codice che ho:

import re 
import sys 

search_term = sys.argv[1] 
f = sys.argv[2] 

for line in open(f, 'r'): 
    if re.search(search_term, line): 
     print line, 
     if line == None: 
      print 'no matches found' 

Ma quando entro in una parola che non è presente, no matches found non stampa

+0

Se si desidera veramente espressioni regolari in stile python in grep, l'opzione --perl-regex su gre p è davvero vicino. Ti offre supporto per espressioni regolari in stile perl. (Inoltre, la mia opzione underused preferita per grep è --color = always) –

risposta

3
  1. uso sys.argv per ottenere i parametri della riga di comando
  2. uso open(), read() per manipolare file di
  3. utilizzare il Python re module a mat ch lines
59

La domanda naturale è perché non usare solo grep ?! Ma a patto che non si può ...

import re 
import sys 

file = open(sys.argv[2], "r") 

for line in file: 
    if re.search(sys.argv[1], line): 
     print line, 

cose da notare:

  • search invece di match a trovare da nessuna parte nella stringa
  • virgola (,) dopo print rimuove ritorno a capo (linea sarà 1)
  • argv include il nome del file python, quindi le variabili devono iniziare da 1

Questo non gestisce più argomenti (come fa grep) o espande i caratteri jolly (come avrebbe fatto la shell Unix). Se si voleva questa funzionalità si potrebbe ottenere utilizzando il seguente:

import re 
import sys 
import glob 

for arg in sys.argv[2:]: 
    for file in glob.iglob(arg): 
     for line in open(file, 'r'): 
      if re.search(sys.argv[1], line): 
       print line, 
+5

dovresti compilare la tua espressione regolare prima di usare i loop. – ghostdog74

+3

Questo ha due voti bassi e non ho idea del perché. Chiunque abbia downvoted desidera lasciare un commento? So che potresti aggiungere la compilazione di espressioni regolari ecc., Ma ho pensato che avrebbe sminuito la chiarezza della risposta. Non penso che ci sia qualcosa di sbagliato, e ho eseguito il codice, a differenza di alcune delle altre risposte –

+0

Questa risposta è stata perfetta per me, grazie. Solo un'altra domanda veloce come potrei stampare se non sono state trovate corrispondenze? – David

5

adattato da un grep in python.

accetta un elenco di nomi di file via [2:], non fa la gestione delle eccezioni:

#!/usr/bin/env python 
import re, sys, os 

for f in filter(os.path.isfile, sys.argv[2:]): 
    for line in open(f).readlines(): 
     if re.match(sys.argv[1], line): 
      print line 

sys.argv[1] resp sys.argv[2:] opere, se lo si esegue come un eseguibile standalone, il che significa

chmod +x

primo

+0

Qual è la differenza tra 're.match' e' re.search'? – OscarRyz

+2

@OscarRyz vedi [Risposta principale di Nick Fortescue] (http://stackoverflow.com/a/1921932/327074): "' search' invece di 'match' per trovare ovunque nella stringa" – icc97

2

Potresti essere interessato a pyp. Citando la mia altra answer:

"Il Pyed Piper", o PYP, è una manipolazione di testo strumento da riga di comando di Linux simile a awk o sed, ma che utilizza stringa standard di Python e metodi delle liste, nonché funzioni personalizzate evoluto per generare velocemente risultati in un intenso ambiente di produzione.

7

concisa ed efficiente della memoria:

#!/usr/bin/env python 
# file: grep.py 
import re, sys 

map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l))) 

Funziona come egrep (senza gestione degli errori troppo), ad esempio:

cat file-to-be-searched | grep.py "RE" 

E qui è l'one-liner:

cat file-to-be-searched | python -c "import re,sys;map(sys.stdout.write,(l for l in sys.stdin if re.search(sys.argv[1],l)))" "RE" 
+1

Questo potrebbe essere rifatto con un generatore e praticamente non avrebbe memoria – vy32

+0

Grazie per averlo indicato. Ho aggiornato la risposta usando solo iteratori. –

+0

È grandioso. Molto ben fatto. – vy32