GNU/Linux >> Linux Esercitazione >  >> Linux

10 esempi pratici di comandi Grep per sviluppatori

Di recente, ho iniziato a lavorare con Asciidoctor.js e su il progetto Asciidoctor.js-pug e Asciidoctor-templates.js.

Non è sempre facile essere immediatamente efficaci quando si scava per la prima volta in una base di codice contenente diverse migliaia di righe. Ma la mia arma segreta per trovare la mia strada attraverso così tante righe di codice è il grep strumento.

Condividerò con te come usare il comando grep in Linux con esempi.

Esempi utili nella vita reale dei comandi grep in Linux

Se guardi dentro man , vedrai quella breve descrizione per grep strumento:"stampa linee che corrispondono a un motivo".

Tuttavia, non lasciarti ingannare da una definizione così umile:grep è uno degli strumenti più utili nella casella degli strumenti Unix e ci sono innumerevoli occasioni per usarlo non appena lavori con file di testo.

È sempre meglio avere esempi del mondo reale per imparare come funzionano le cose. Quindi, userò l'albero dei sorgenti di Asciidoctor.js per illustrare alcuni dei grep capacità.

Puoi scaricare quell'albero dei sorgenti da GitHub e, se lo desideri, puoi anche controllare lo stesso set di modifiche che ho usato quando ho scritto questo articolo. Ciò ti assicurerà di ottenere risultati perfettamente identici a quelli descritti nel resto di questo articolo:

git clone https://github.com/asciidoctor/asciidoctor.js
cd asciidoctor.js
git checkout v1.5.6-rc.1

1. Trova tutte le occorrenze di una stringa (utilizzo di base)

Asciidoctor.js supporta il motore JavaScript Nashorn per la piattaforma Java. Non conosco Nashorn, quindi potrei cogliere l'occasione per saperne di più esplorando le parti del progetto che fanno riferimento a quel motore JavaScript.

Come punto di partenza, ho verificato se c'erano alcune impostazioni relative a Nashorn nel package.json file che descrive le dipendenze del progetto:

[email protected]:~$ grep nashorn package.json
    "test": "node npm/test/builder.js && node npm/test/unsupported-features.js && node npm/test/jasmine-browser.js && node npm/test/jasmine-browser-min.js && node npm/test/jasmine-node.js && node npm/test/jasmine-webpack.js && npm run test:karmaBrowserify && npm run test:karmaRequirejs && node npm/test/nashorn.js",

Sì, a quanto pare c'erano alcuni test specifici di Nashorn. Quindi, indaghiamo un po' di più.

2. Ricerca senza distinzione tra maiuscole e minuscole in un set di file

Ora, voglio dare un'occhiata più da vicino ai file da ./npm/test/ directory che menziona esplicitamente Nashorn.

Una ricerca senza distinzione tra maiuscole e minuscole (-i opzione) è probabilmente migliore qui poiché ho bisogno di trovare entrambi i riferimenti a nashorn e Nashorn (o qualsiasi altra combinazione di caratteri maiuscoli e minuscoli):

[email protected]:~$ grep -i nashorn npm/test/*.js
npm/test/nashorn.js:const nashornModule = require('../module/nashorn');
npm/test/nashorn.js:log.task('Nashorn');
npm/test/nashorn.js:nashornModule.nashornRun('jdk1.8.0');

In effetti, la distinzione tra maiuscole e minuscole è stata utile qui. Altrimenti, mi sarei perso il require('../module/nashorn') dichiarazione. Senza dubbio dovrei esaminare quel file in modo più dettagliato in seguito.

3. Trova tutti i file non corrispondenti

A proposito, ci sono alcuni file non specifici di Nashorm nel npm/test/ directory? Per rispondere a questa domanda, possiamo usare l'opzione "stampa file non corrispondenti" di grep (-L opzione):

sh$ grep -iL nashorn npm/test/*
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js

Nota come con -L opzione l'output di grep è cambiato per visualizzare solo i nomi dei file. Quindi, nessuno dei file sopra contiene la stringa "nashorn" (indipendentemente dal caso). Ciò non significa che non siano in qualche modo correlati a quella tecnologia, ma almeno le lettere "n-a-s-h-o-r-n" non sono presenti.

4. Trovare modelli in file nascosti e ricorsivamente in sottodirectory

Gli ultimi due comandi utilizzavano un pattern shell glob per passare l'elenco dei file da esaminare a grep comando.

Tuttavia, questo ha alcune limitazioni intrinseche:la stella (* ) non corrisponderà ai file nascosti. Né corrisponderà ai file (eventualmente) contenuti nelle sottodirectory.

Una soluzione sarebbe combinare grep con il comando find invece di fare affidamento su un pattern di shell glob:

# This is not efficient as it will spawn a new grep process for each file
[email protected]:~$ find npm/test/ -type f -exec grep -iL nashorn \{} \;
# This may have issues with filenames containing space-like characters
[email protected]:~$ grep -iL nashorn $(find npm/test/ -type f)

Come l'ho menzionato commentando il blocco di codice sopra, ognuna di queste soluzioni presenta degli svantaggi.

Per quanto riguarda i nomi di file contenenti caratteri simili a spazi, ti lascio esaminare il grep -z opzione che, combinata con il -print0 opzione del find comando, può attenuare il problema. Non esitare a utilizzare la sezione commenti alla fine di questo articolo per condividere le tue idee su quell'argomento!

Tuttavia, una soluzione migliore potrebbe utilizzare il "ricorsivo" (-r ) opzione di grep . Con questa opzione, fornisci sulla riga di comando la radice del tuo albero di ricerca (la directory iniziale) invece dell'elenco esplicito di nomi di file da esaminare.

Con il -r opzione, grep cercherà tutti i file nella directory specificata, inclusi quelli nascosti, e quindi scenderà ricorsivamente in qualsiasi sottodirectory:

[email protected]:~$ grep -irL nashorn npm/test/npm/
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js

In realtà, con quell'opzione, potrei anche iniziare la mia esplorazione un livello sopra per vedere che ci sono test non npm che prendono di mira anche Nashorn:

[email protected]:~$ grep -irL nashorn npm/

Ti ho lasciato testare da solo quel comando per vederne l'esito; ma come suggerimento, posso dire che dovresti trovare molti più file corrispondenti!

5. Filtraggio dei file per nome (usando espressioni regolari)

Quindi, sembra che ci siano alcuni test specifici di Nashorn in quel progetto. Poiché Nashorn è Java, un'altra domanda che potrebbe essere sollevata sarebbe "ci sono alcuni file sorgente Java nel progetto che menzionano esplicitamente Nashorn?" .

A seconda della versione di grep che usi, ci sono almeno due soluzioni per rispondere a questa domanda.

Il primo è usare grep per trovare tutti i file contenenti il ​​pattern "nashorn", quindi reindirizzare l'output di quel primo comando a un secondo grep istanza che filtra i file di origine non Java:

[email protected]:~$ grep -ir nashorn ./ | grep "^[^:]*\.java"
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/basic.js"));

La prima metà del comando dovrebbe essere ormai comprensibile. Ma che dire di quella parte “^[\^:]*\\.java”?

A meno che non specifichi il -F opzione, grep presuppone che il modello di ricerca sia un'espressione regolare. Ciò significa che, oltre ai caratteri semplici che corrisponderanno alla lettera, hai accesso a una serie di metacaratteri per descrivere schemi più complessi. Il modello che ho usato sopra corrisponderà solo a:

  • ^ l'inizio della riga
  • [^:]* seguito da una sequenza di qualsiasi carattere tranne i due punti
  • \. seguito da un punto (il punto ha un significato speciale in regex , quindi ho dovuto proteggerlo con una barra rovesciata per esprimere che voglio una corrispondenza letterale)
  • java e seguito dalle quattro lettere "java".

In pratica, poiché grep utilizzerà i due punti per separare il nome del file dal contesto, conservo solo le righe con .java nella sezione nome file. Vale la pena menzionarlo sarebbe trova anche .javascript nomi di file. Questo è qualcosa che ho lasciato provare a risolvere da solo, se lo desideri.

6. Filtrare i file in base al nome usando grep

Le espressioni regolari sono estremamente potenti. Tuttavia, in quel caso particolare, sembra eccessivo. Senza menzionare la soluzione di cui sopra, passiamo del tempo a esaminare tutti i file alla ricerca del modello "nashorn":la maggior parte dei risultati viene eliminata dal secondo passaggio della pipeline.

Se stai usando la versione GNU di grep , qualcosa che è probabile se stai usando Linux, hai un'altra soluzione anche se con --include opzione. Questo indica grep per cercare solo nei file il cui nome corrisponde al pattern glob specificato:

[email protected]:~$ grep -ir nashorn ./ --include='*.java'
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/basic.js"));

7. Trovare le parole

La cosa interessante del progetto Asciidoctor.js è che è un progetto multilingue. Al suo interno, Asciidoctor è scritto in Ruby, quindi, per essere utilizzabile nel mondo JavaScript, deve essere "traspilato" usando Opal, un compilatore da sorgente a sorgente da Ruby a JavaScript. Un'altra tecnologia che non conoscevo prima.

Quindi, dopo aver esaminato le specificità del Nashorn, mi sono affidato il compito di comprendere meglio l'API Opal. Come primo passo in quella ricerca, ho cercato tutte le menzioni di Opal oggetto globale nei file JavaScript del progetto. Potrebbe apparire con affettazioni (Opal = ), accesso membri (Opal. ) o forse anche in altri contesti. Un'espressione regolare farebbe il trucco. Tuttavia, ancora una volta, grep ha una soluzione più leggera per risolvere quel caso d'uso comune. Usando il -w opzione, corrisponderà solo a parole , ovvero schemi preceduti e seguiti da un carattere non di parola. Un carattere diverso da una parola è l'inizio della riga, la fine della riga o qualsiasi carattere che non sia una lettera, né una cifra, né un trattino basso:

[email protected]:~$ grep -irw --include='*.js' Opal .
...

8. colorando l'output

Non ho copiato l'output del comando precedente poiché ci sono molte corrispondenze. Quando l'output è così denso, potresti voler aggiungere un po' di colore per facilitare la comprensione. Se questo non è già configurato per impostazione predefinita sul tuo sistema, puoi attivare quella funzione usando GNU --color opzione:

[email protected]:~$ grep -irw --color=auto --include='*.js' Opal .
...

Dovresti ottenere lo stesso risultato lungo di prima, ma questa volta la stringa di ricerca dovrebbe apparire a colori se non era già il caso.

9. Conteggio delle righe corrispondenti o dei file corrispondenti

Ho menzionato due volte che l'output dei comandi precedenti era molto lungo. Quanto tempo esattamente?

[email protected]:~$ grep -irw --include='*.js' Opal . | wc -l
86

Ciò significa che abbiamo un totale 86 righe corrispondenti in tutte i fascicoli esaminati. Tuttavia, quanti file diversi corrispondono? Con il -l opzione puoi limitare il grep genera i file corrispondenti invece di visualizzare le linee corrispondenti . Quindi quella semplice modifica indicherà quanti file corrispondono:

[email protected]:~$ grep -irwl --include='*.js' Opal . | wc -l
20

Se questo ti ricorda il -L opzione, nessuna sorpresa:poiché è relativamente comune, minuscole/maiuscole vengono utilizzate per distinguere le opzioni complementari. -l visualizza i nomi di file corrispondenti. -L visualizza nomi di file non corrispondenti. Per un altro esempio, ti lascio controllare il manuale per il -h /-H opzioni.

Chiudiamo quella parentesi e torniamo ai nostri risultati:86 righe corrispondenti. 20 file corrispondenti. Tuttavia, come vengono distribuite le linee corrispondenti nei file corrispondenti ? Possiamo saperlo usando il -c opzione di grep che conterà il numero di righe corrispondenti per file esaminato (compresi i file con zero corrispondenze):

[email protected]:~$ grep -irwc --include='*.js' Opal .
...

Spesso, quell'output necessita di una post-elaborazione poiché mostra i suoi risultati nell'ordine in cui i file sono stati esaminati e include anche file senza alcuna corrispondenza, cosa che di solito non ci interessa. Quest'ultimo è abbastanza facile da risolvere:

[email protected]:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$'

Per quanto riguarda l'ordine, puoi aggiungere il comando sort alla fine della pipeline:

[email protected]:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$' | sort -t: -k2n

Ti lascio controllare il sort manuale dei comandi per il significato esatto delle opzioni che ho usato. Non dimenticare di condividere i tuoi risultati utilizzando la sezione commenti qui sotto!

10. Trovare la differenza tra due set corrispondenti

Se ricordi, qualche comando fa ho cercato la parola "Opale." Tuttavia, se cerco nello stesso set di file per tutte le occorrenze della stringa “Opale”, ottengo una ventina di risposte in più:

[email protected]:~$ grep -irw --include='*.js' Opal . | wc -l
86
[email protected]:~$ grep -ir --include='*.js' Opal . | wc -l
105

Sarebbe interessante trovare la differenza tra questi due set. Quindi, quali sono le righe che contengono le quattro lettere "opale" di seguito, ma dove quelle quattro lettere non formano un'intera parola?

Non è così facile rispondere a questa domanda. Perché lo uguale la riga può contenere entrambi la parola Opal così come una parola più grande contenente quelle quattro lettere. Ma come prima approssimazione, puoi usare quella pipeline:

[email protected]:~$ grep -ir --include='*.js' Opal . | grep -ivw Opal
./npm/examples.js:  const opalBuilder = OpalBuilder.create();
./npm/examples.js:  opalBuilder.appendPaths('build/asciidoctor/lib');
./npm/examples.js:  opalBuilder.appendPaths('lib');
...

Apparentemente, la mia prossima tappa sarebbe indagare su opalBuilder oggetto, ma sarà per un altro giorno.

L'ultima parola

Ovviamente, non capirai l'organizzazione di un progetto, tanto meno l'architettura del codice, semplicemente emettendo un paio di grep comandi!

Tuttavia, trovo quel comando inevitabile per identificare benchmark e punti di partenza quando si esplora una nuova base di codice.

Quindi, spero che questo articolo ti abbia aiutato a capire la potenza di grep comando e che lo aggiungerai alla tua cassetta degli attrezzi. Senza dubbio non te ne pentirai!


Linux
  1. 8 esempi pratici del comando Xargs di Linux per principianti

  2. Esempi di comandi DNF per principianti

  3. 10 esempi pratici di utilizzo del comando scp

  4. Comando cp in Linux:7 esempi pratici

  5. Comando nslookup:7 esempi pratici

12 Esempi pratici di In Command in Linux

I 40 esempi di comandi Go per aspiranti sviluppatori Golang

15 esempi pratici di comando Rsync in Linux

5 esempi pratici di Tail Command in Linux

15 Esempi pratici di comandi Grep in Linux / UNIX

UNIX / Linux:7 esempi pratici di comandi PS per il monitoraggio dei processi