Senza la necessità di installare la variante grep pcregrep
, puoi eseguire una ricerca su più righe con grep.
$ grep -Pzo "(?s)^(\s*)\N*main.*?{.*?^\1}" *.c
Spiegazione:
-P
attiva perl-regexp per grep (una potente estensione delle espressioni regolari)
-z
Considera l'input come un insieme di righe, ciascuna terminata da un byte zero (il carattere ASCII NUL) anziché da una nuova riga. Cioè, grep sa dove sono le estremità delle linee, ma vede l'input come un'unica grande linea. Attenzione questo aggiunge anche un carattere NUL finale se usato con -o
, vedi i commenti.
-o
stampa solo corrispondenza. Perché stiamo usando -z
, l'intero file è come un'unica grande linea, quindi se c'è una corrispondenza, l'intero file verrebbe stampato; in questo modo non lo farà.
Nell'espressione regolare:
(?s)
attiva PCRE_DOTALL
, il che significa che .
trova qualsiasi carattere o nuova riga
\N
trova qualsiasi cosa tranne la nuova riga, anche con PCRE_DOTALL
attivato
.*?
trova .
in modalità non golosa, ovvero si interrompe il prima possibile.
^
trova l'inizio della riga
\1
backreference al primo gruppo (\s*
). Questo è un tentativo di trovare la stessa indentazione di metodo.
Come puoi immaginare, questa ricerca stampa il metodo main in un file C (*.c
) file sorgente.
Non sono molto bravo in grep. Ma il tuo problema può essere risolto usando il comando AWK. Basta vedere
awk '/select/,/from/' *.sql
Il codice precedente risulterà dalla prima occorrenza di select
fino alla prima sequenza di from
. Ora devi verificare se le istruzioni restituite contengono customername
o no. Per questo puoi convogliare il risultato. E può usare di nuovo awk o grep.