Bash: c'è un modo per cercare una stringa particolare in una directory di file? [duplicare]


47

Possibile duplicato:
cerca un modello di testo in Linux

In bash, mi chiedevo se ci fossero dei comandi che ti avrebbero fatto sapere se una particolare stringa che stai cercando esiste all'interno dei file che si trovano nella directory corrente in cui ti trovi.

Supponiamo che tu stia cercando la funzione 'toUpperCase ()' all'interno di un set di file C nella directory corrente. Ci sono molti file, quindi non vorrai aprirli manualmente usando vim e controllare la stringa 'toUpperCase' perché ciò richiederebbe molto tempo. Se non una riga di comando bash, esiste un altro metodo per farlo in modo efficiente?

Risposte:


64

Con grep:

grep -R "toUppercase()" *

Oppure, se hai ack-grep installato, semplicemente:

ack-grep "toUppercase"

Se si desidera limitare la ricerca in file C, con ack-grep:

ack-grep -cc "toUppercase()"

ack-greppuò anche essere installato su OSX ma l'eseguibile si chiama just ack.


Tanto che SO ha già una domanda sospettosamente simile ;)
David Perry,

10

Lo strumento di ricerca di testo standard è grep .

Per cercare la stringa toUpperCase(in tutti i .cfile nella directory corrente:

grep -F 'toUpperCase(' *.c

Se vuoi cercare anche nelle sottodirectory:

grep -r --include='*.c' -F 'toUpperCase('

Se stai cercando chiamate di funzione C, i tag possono essere più adatti. Lo esegui una volta su tutti i tuoi file sorgente per creare un indice di identificatori, quindi usi il tuo editor per navigare tra le chiamate. Tutti gli editor di tipo vi possono utilizzare il TAGSfile ctags . Se usi Emacs, esegui il programma simile etags.


ctagsè utile per trovare definizioni di funzioni , non chiamate di funzione .
JdeBP,

6

Stai usando Vim. Hai uno strumento per farlo incorporato.

Com'era prevedibile, ci sono già sette risposte che dicono di usare grep. Ma mi sembra di essere l'unica persona finora che ha notato dalla tua domanda che stai usando vim. Pertanto, sebbene sia possibile utilizzarlo grepdall'interno vim, è anche possibile utilizzare lo vimstrumento integrato. Questo viene invocato tramite il :vimgrepcomando.

Per cercare "tutti i file sorgente C nella directory corrente per le chiamate alla funzione toUpperCase()" si digita il vimcomando

:vimgrep "\<toUpperCase\_s*(" *.c

L'elenco di corrispondenze risultante viene automaticamente caricato nell'elenco di correzioni rapide, accessibile con uno dei due (consultare la guida in linea per la sottile differenza)

:copen
:cwin

Trovare la definizione della funzione , piuttosto che chiamarla, ctagsè lo strumento, come menzionato nella Gillesrisposta , in combinazione con i comandi :tjumpo :tselect.

Perché l'uso :vimgrep?

L'help on-line ( :help grep) enumera molte delle ragioni, che non pappagallo qui. Oltre a quelli, confronta l'azione di :vimgrepcon quella della dietbuddharisposta . dietbuddhaLa riga di comando genera un singolo grepprocesso per ogni singolo file sorgente C. Non ha nemmeno bisogno xargsdi ridurre questo sovraccarico. E devi ancora in qualche modo analizzare l'output per invocare il tuo editor di testo sui file sorgente pertinenti una volta che è finito. :vimgrepnon interrompe più processi aggiuntivi e l'utilizzo del risultato è la semplicità stessa. Selezionando semplicemente una delle voci nell'elenco risultante della correzione rapida si posiziona automaticamente il cursore sulla riga pertinente del file sorgente pertinente.

In effetti, fa esattamente quello che hai scritto che faresti a mano, tranne automaticamente. È il modo automatizzato di eseguire quelle azioni dell'editor di testo. Carica il file come se fosse caricato a mano, cerca un'espressione regolare (utilizzando la stessa sintassi di espressioni regolari che stai già utilizzando altrove vim), registra i luoghi in cui si verificano le corrispondenze e quindi scarica il file.


2

Sì, lo strumento viene chiamato grep.

Il comando grep cerca uno o più file di input alla ricerca di righe contenenti una corrispondenza con un modello specificato. Per impostazione predefinita, grep stampa le linee corrispondenti.

L'utilizzo di base è:

grep something somewhere

O, più specificamente:

grep [some options] pattern file

In un caso molto semplice, si desidera ricorsivamente cercare tra tutti i file, quindi si fornisce l' -ropzione. Se non ti importa di maiuscole o minuscole, rendi case-sensitive con l' -iopzione.

grep -ri "touppercase()" .

Se si desidera solo le parti corrispondenti, utilizzare l' -oopzione.

Grep può usare espressioni regolari e ha un enorme manuale .


2

grepè la risposta standard - usare il flag -r per cercare ricorsivamente o insieme find(discussione ed esempi in altre domande su questo sito, come questo )

La mia scelta preferita ultimamente è ack. Probabilmente non è installato sul tuo computer, ma puoi installarlo usando apt-get su Ubuntu o semplicemente scaricarlo. Link, istruzioni e motivi per cui è meglio di grep sono disponibili su http://betterthangrep.com/


1

find e grep

find myproject -name '*.c' -exec grep 'toUpperCase(' {} \; -print

perché non solo grep?

grep -r string .ricercherà attraverso tutti i file nella directory corrente. Se si dispone di file oggetto o altri file binari, è possibile ottenere una corrispondenza con risultati binari, ovvero aka. spazzatura. Se ti capita di avere anche file cinquos o device nella tua sottodirectory, potresti avere conseguenze sconosciute / non intenzionali.

grep string *.ccerca solo i .cfile delle directory correnti .

grep string **/*.c cerca in tutte le sottodirectory. Tuttavia, se si dispone di un numero molto elevato di .cfile, si corre il rischio di superare il numero massimo di espansioni per il glob shell. L'espansione deve anche avvenire per prima, il che significa che attraversa un albero pieno prima che grepinizi.


0

Grep farà il trucco, ma un po 'di script aggiuntivi aiuteranno a trovare il nome del file e la riga esatta a cui si fa riferimento. Se è quello che vuoi, trovo che ciò che segue funzioni bene. L'ho salvato come script di shell e gli ho passato il valore desiderato come prima opzione della riga di comando.

for i in $(ls)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?
    if [ $STATUS  -eq 0 ] ; then
        echo $i
        cat $i | grep -n $1
    fi
done

3
grep ha un'opzione -H che lo fa già. grep -Ciao *
Roy Rico,

Impara qualcosa di nuovo ogni giorno .. Grazie @Roy Rico
Tim Brigham,

0

Trovo interessante che nessuno abbia risposto alla tua domanda specifica: "come faccio a sapere se esiste una stringa particolare all'interno dei file che si trovano nella directory corrente". Per quanto ne so, non esiste un'opzione grep che ritorni solo se è stata trovata una corrispondenza in un gruppo di file. L'opzione più vicina è -l per elencare i nomi dei file. La risposta più vicina tra quelle finora è di Tim, con alcune lievi modifiche:

#!/usr/bin/bash

for i in $(ls *.c 2> /dev/null)
do
    cat $i 2> /dev/null | grep $1 > /dev/null 2>&1
    STATUS=$?

    if [ $STATUS  -eq 0 ] ; then
        echo "Found"
        exit
    fi
done

echo "Not found"

È possibile rendere questo script di shell più generico accettando un secondo argomento per l'estensione del file senza troppi problemi.

Doug

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.