Encontre um arquivo de texto contendo um determinado texto ignorando novas linhas e espaços?

3

Eu tenho uma string como: "thisissometext" . Eu quero encontrar todos os arquivos de texto dentro de um determinado diretório (recursivamente) que contenham essa seqüência, ou qualquer variação dela com espaços em branco e / ou novas linhas no meio dela. Por exemplo, um arquivo de texto contendo "this is sometext" ou "this\n issometext" , "this\n isso metext" deve aparecer na pesquisa. Como posso fazer isso?

    
por becko 27.05.2015 / 21:02

4 respostas

10

Com as versões mais recentes do GNU grep (que tem a opção -z ), você pode usar este forro:

find . -type f -exec grep -lz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' {} +

Considerando que os espaços em branco podem estar entre as palavras apenas.

Se você quiser pesquisar todos os arquivos recursivamente a partir do diretório atual, não precisará de find , basta usar grep -r (recursivo). find pode ser usado para ser seletivo nos arquivos a pesquisar, por ex. escolha arquivos de qual diretório excluir. Então, simplesmente:

grep -rlz 'this[[:space:]]*is[[:space:]]*some[[:space:]]*text' .
  • O principal truque aqui é -z , ele tratará cada linha de fluxo de entrada terminada em ASCII NUL em vez de nova linha, como resultado, podemos combinar novas linhas usando métodos usuais.

  • O padrão de classe de caractere [[:space:]] indica qualquer caractere de espaço em branco, incluindo espaço, tabulação, CR, LF etc. Portanto, podemos usá-lo para corresponder a todos os caracteres em branco que podem aparecer entre as palavras.

  • grep -l imprimirá apenas os nomes dos arquivos que tiverem algum dos padrões desejados. Se você quiser imprimir as correspondências também, use -H em vez de -l .

Por outro lado, se os espaços em branco puderem vir em qualquer lugar e não nas palavras, isso perderá sua boa aparência:

grep -rlz
't[[:space:]]*h[[:space:]]*i[[:space:]]*s[[:space:]]*i[[:space:]]*\
s[[:space:]]*s[[:space:]]*o[[:space:]]*m[[:space:]]*e[[:space:]]*\
t[[:space:]]*e[[:space:]]*x[[:space:]]*t' .

Com a opção -P (PCRE), você pode substituir o [[:space:]] por \s (isso pareceria muito melhor):

grep -rlzP 't\s*h\s*i\s*s\s*i\s*s\s*s\s*o\s*m\s*e\s*\
t\s*e\s*x\s*t' .

Usar a sugestão do @ steeldriver para obter sed para gerar o padrão para nós seria a melhor opção:

grep -rlzP "$(sed 's/./\s*&/2g' <<< "thisissometext")" .
    
por heemayl 27.05.2015 / 23:07
5

Você pode excluir todo o espaço em branco e aplicá-lo:

tr -d '[[:space:]]' < foo | grep thisissometext

Estendendo:

find . -type f -exec bash -c 'for i; do tr -d "[[:space:]]" < "$i" | grep -q thisissometext && printf "%s\n" "$i"; done' _ {} +

O comando bash , expandido:

for i
do
    tr -d "[[:space:]]" < "$i" | 
      grep -q thisissometext && 
      printf "%s\n" "$i"
done

Isso faz um loop sobre todos os argumentos e usa o teste acima.

    
por muru 27.05.2015 / 22:16
1

O código abaixo pesquisa um diretório recursivamente para arquivos, remove todas as ocorrências de " " e "\n" . Se a string existir no texto restante, haverá uma correspondência. Isto implica que os espaços / novas linhas podem estar em qualquer posição na cadeia dentro do (s) seu (s) arquivo (s).

O que faz

Se encontrar arquivos correspondentes, eles serão impressos no terminal, incluindo seus caminhos, como:

/home/jacob/Bureaublad/testmap/test2.txt
/home/jacob/Bureaublad/testmap/Naamloze map 2/test1.txt

O try / exceto que eu criei para impedir que o script quebre se ele for executado em um arquivo ilegível.

O script

#!/usr/bin/env python3
import os
import sys

s = sys.argv[2]
for root, dirs, files in os.walk(sys.argv[1]):
    for file in files:
        file = root+"/"+file
        try:
            if s in open(file).read().replace(" ", "").replace("\n",""):
                print(file)
        except:
            pass

Como usar

  1. Copie o script em um arquivo vazio, salve-o como find_string.py
  2. Execute-o com o diretório e a string como argumentos:

    python3 /path/to/find_string.py <directory> <string_to_find>
    

    Se a string ou o diretório contiverem espaços, use aspas:

    python3 /path/to/find_string.py '<directory>' '<string_to_find>'
    

Nota

O script, como é encontrado arquivos com a string, com espaços em branco ou novas linhas nele. Ele pode ser expandido com outros caracteres / strings (por exemplo, guias) na linha:

if s in open(file).read().replace(" ", "").replace("\n",""):
    
por Jacob Vlijm 27.05.2015 / 21:31
0

Você pode usar grep -i --recursive 'word1\|word2' * e awk '/word1/,/word2/' para lidar com a nova linha

    
por Sergiy Kolodyazhnyy 27.05.2015 / 21:47