Motivo multilinea Grep


13

Come posso cercare una frase su più righe? Ad esempio, abbiamo la frase "il mio tè freddo", quindi può essere racchiusa in file di testo:

as js skdfh dfh djh sf my
ice tea.

grep non corrisponderà poiché c'è una nuova riga in mezzo. Come posso abbinarli? Un altro modello multilinea sarebbepattern1_\n_pattern2

So che il modo più semplice di fare ATM è solo grep per una parte, ad es. Solo ghiaccio con flag -A2 -B2 e quindi in quell'output per esempio il tè. Ma questo è molto noioso. Quindi sono interessato a come risolverlo.


Risposte:


16

Potresti installare pcregrep(disponibile nella maggior parte dei repository di distro) - che è grep usando la libreria pcre , che fa "Espressioni regolari compatibili Perl". Ha un'opzione da riga di comando -Mche ti permette di fare ricerche su più righe - dalla pagina man :

"L'output per ogni corrispondenza può essere costituito da più di una riga."

Quindi potresti farlo

pcregrep -M 'my\s+ice\s+tea' filename

È lo \sspazio bianco, che corrisponderà \ne \rin modalità multilinea, oltre ai normali caratteri degli spazi bianchi. Puoi anche abbinare direttamente il carattere di nuova riga, così puoi farlo

pcregrep -M 'pattern1_\n_pattern2' filename

+1 simpatico. mai sentito parlare, ma l'ho provato e funziona come un incantesimo!
DaveParillo,

Non grep -Efa schemi pcre?
Daenyth,

3
@Daenyth grep -E per lo più solo significa che è possibile utilizzare ?, +, {, |, (, e )come al loro senso abituale espressione regolare, senza dover disporre di un \ fronte, come si fa se si utilizza grep standard. Quindi grep 'hello\s\+world' fileè equivalente a grep -E 'hello\s+world' file. Non fa PCRE. Esistono grep -Pespressioni regolari perl, ma è sperimentale (secondo la pagina man) e penso che sia un po 'diverso da pcregrep ...
Hamish Downer

1
Sì, stavo pensando a -Pquando ho detto -E, ma non mi ero reso conto che fosse diverso.
Daenyth,

3

Probabilmente farei una ricerca usando vimil :vimgrepcomando di. Funziona in modo vagamente simile a quello di grepma supporta Vim REs e percorsi.

Fondamentalmente si esegue qualcosa di simile :vimgrep 'pattern1\npattern2' path/**a una ricerca ricorsiva, quindi si digita :copenper visualizzare una finestra più piccola contenente un elenco di corrispondenze.

vimLe RE possono fare quasi tutto ciò che i PCRE possono fare, ma si sono evolute separatamente dalla stirpe delle espressioni regolari perl, quindi la maggior parte delle cose avanzate funziona in modo diverso. La loro funzionalità di base è più simile a quella delle RE di base, ma hanno alcune aggiunte intelligenti che i PCRE non offrono.

Non sono sicuro che sia possibile :vimgrepsputare dati allo grepstesso modo; Ho sempre provato a usarlo per la navigazione all'interno vim.

:help vimgrepdall'interno vimper maggiori informazioni; :help pattern.txtper informazioni su vimRE; per maggiori informazioni sui percorsi vedere :help wildcards.


Fai attenzione: non è del tutto portatile in quanto si comporterà in modo diverso su piattaforme diverse
Daenyth,

1
@Daenyth: intendi sotto l'influenza di diversi .vimrc? Dovrebbe essere più portatile greprispetto al sistema operativo: vimnon ha un "sapore POSIX" e funziona più o meno in modo identico anche con Windows. .................................................. ........................... È possibile aggiungere qualificatori per garantire, ad esempio, che la giusta quantità di "magia" venga utilizzata su RE a quanto ho capito, esiste una rigida regola non scritta per lasciare solo questa opzione.
intuito il

Non l'ho usato da solo, ma a quanto pare utilizza un backend diverso su Windows ( find.exeanziché grep). C'è stata un'altra domanda nelle ultime settimane che ha avuto quel problema.
Daenyth,

1
@Daenyth: stai pensando :vimgrepo :grep? Da :help grep: "Il vantaggio del grep interno [ie :vimgrep] è che funziona su tutti i sistemi e utilizza i potenti schemi di ricerca di Vim."
intuito il

1
Ah, deve essere quello. Ho confuso i due.
Daenyth,

2

Grep funziona solo su una riga alla volta, ma è possibile utilizzare awk per stampare righe corrispondenti a una serie di motivi:

cat file | awk '/foo/,/bar/'

corrisponderebbe a tutto, non solo alle nuove linee tra i due modelli


0

Per ottenere il massimo da unix è necessario sfruttare i tubi. Puoi farlo semplicemente grepusando le pipe (non c'è bisogno di tee):

$ grep -A1 "pattern1" file.txt |  grep "pattern2"

Che non considererei noioso.


Penso che questo sia soggetto a errori, poiché tra pattern1 e pattern2 può esistere pattern3 che potrebbe non essere quello che stai cercando. Quindi devi controllare ogni colpo manualmente.
matematica,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.