GNU/Linux >> Linux Esercitazione >  >> Linux

Cercare file di testo in cui esistono due parole diverse (qualsiasi ordine, qualsiasi riga)?

Sto cercando un modo per cercare file in cui esistono due istanze di parole nello stesso file. Finora ho utilizzato quanto segue per eseguire le mie ricerche:

find . -exec grep -l "FIND ME" {} ;

Il problema che sto riscontrando è che se non c'è esattamente uno spazio tra "TROVA" e "ME", il risultato della ricerca non restituisce il file. Come posso adattare la precedente stringa di ricerca in cui entrambe le parole "TROVA" e "MI esistono in un file invece di "TROVAMI"?

Sto usando AIX.

Risposta accettata:

Con gli strumenti GNU:

find . -type f  -exec grep -lZ FIND {} + | xargs -r0 grep -l ME

Puoi fare di serie:

find . -type f -exec grep -q FIND {} ; -exec grep -l ME {} ;

Ma ciò comporterebbe fino a due grep s per file. Per evitare di eseguire così tanti grep s ed essere ancora portatile pur consentendo qualsiasi carattere nei nomi dei file, potresti fare:

convert_to_xargs() {
  sed "s/[[:blank:]"']/\\&/g" | awk '
    {
      if (NR > 1) {
        printf "%s", line
        if (!index($0, "//")) printf "\"
        print ""
      }
      line = $0
    }'
    END { print line }'
}

export LC_ALL=C
find .//. -type f |
  convert_to_xargs |
  xargs grep -l FIND |
  convert_to_xargs |
  xargs grep -l ME

L'idea è di convertire l'output di find in un formato adatto per xargs (che si aspetta uno spazio vuoto (SPC/TAB/NL nel C locale, YMMV in altre impostazioni locali) elenco separato di parole in cui le virgolette singole, doppie e le barre inverse possono sfuggire agli spazi vuoti e tra loro).

In genere non puoi post-elaborare l'output di find -print , perché separa i nomi dei file con un carattere di nuova riga e non sfugge ai caratteri di nuova riga che si trovano nei nomi dei file. Ad esempio se vediamo:

./a
./b

Non abbiamo modo di sapere se si tratta di un file chiamato b in una directory chiamata a<NL>. o se sono i due file a e b nella directory corrente.

Usando .//. , perché // non può apparire altrimenti in un percorso di file come output di find (perché non esiste una directory con un nome vuoto e / non è consentito in un nome di file), sappiamo che se vediamo una riga che contiene // , quindi questa è la prima riga di un nuovo nome file. Quindi possiamo usare quel awk comando per eseguire l'escape di tutti i caratteri di nuova riga tranne quelli che precedono quelle righe.

Se prendiamo l'esempio sopra, find verrebbe prodotto nel primo caso (un file):

.//a
./b

Quale awk sfugge a:

.//a
./b

Quindi xargs lo vede come un argomento. E nel secondo caso (due file):

.//a
.//b

Quale awk lascerebbe così com'è, quindi xargs vede due argomenti.

Correlati:la modalità mouse di Tmux attiva non consente di selezionare il testo con il mouse?

Hai bisogno del LC_ALL=C quindi sed , awk (e alcune implementazioni di xargs ) funzionano per sequenze arbitrarie di byte (anche se non formano caratteri validi nelle impostazioni locali dell'utente), per semplificare lo vuoto definizione ai soli SPC e TAB e per evitare problemi con interpretazioni diverse di caratteri la cui codifica contiene la codifica di backslash da parte delle diverse utilità.


Linux
  1. Confronta due colonne di file diversi e stampa se corrisponde?

  2. Come cercare i file per dimensione ed estensione?

  3. Linux:dove sono i metadati per i file Pdf? Posso inserire metadati in qualsiasi file Pdf?

  4. Cercare file i cui percorsi contengono più parole senza un ordine specifico tra di loro?

  5. Usa Trova e trova per cercare file in Linux

Newsboat:un lettore di feed RSS/Atom da riga di comando per console di testo

Come aggiungere numeri di riga a file di testo su Linux

Come cercare file dalla riga di comando di Linux

Come trovare file contenenti una stringa di testo specifica in Linux

Come cercare un file nei file war,ear e jar in modo ricorsivo in Linux

Trova qualsiasi riga in VI che abbia qualcosa di diverso da ATCG