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

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

Eu tenho uma string como: "thisissometext". Quero encontrar todos os arquivos de texto dentro de um determinado diretório (recursivamente) que contenha essa string, 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?

Responder1

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

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

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

Se você deseja apenas pesquisar todos os arquivos recursivamente a partir do diretório atual, não precisa find, basta usar grep -r(recursivo). findpode ser usado para ser seletivo nos arquivos a serem pesquisados, por exemplo, escolher os arquivos de qual diretório excluir. Então, simplesmente:

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

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

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

Por outro lado, se os espaços em branco pudessem vir em qualquer lugar em vez das palavras, isso perderia a 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 -Pa opção (PCRE) você pode substituir [[:space:]]por \s(ficaria 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 de @steeldriver para sedgerar o padrão para nós seria a melhor opção:

grep -rlzP "$(sed 's/./\\s*&/2g' <<< "thisissometext")" .

Responder2

Você pode excluir todos os espaços em branco e fazer o grep:

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 bashcomando, expandido:

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

Isso percorre todos os argumentos e usa o teste acima.

Responder3

O código abaixo pesquisa arquivos recursivamente em um diretório, remove todas as ocorrências de " "e "\n". Se a string existir no texto restante, há uma correspondência. Isso implica que os espaços/novas linhas podem estar emqualquerposição na string 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 / except que eu incorporei para evitar que o script seja quebrado se for executado em um arquivo ilegível.

O roteiro

#!/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 e salve-o comofind_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 contiver espaços, use aspas:

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

Observação

O script, tal como está, encontra arquivos com a string, com espaços em branco ou novas linhas. Pode ser expandido com outros caracteres/strings (por exemplo, tabulações) na linha:

if s in open(file).read().replace(" ", "").replace("\n",""):

Responder4

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

insira a descrição da imagem aqui

informação relacionada