Estou procurando uma maneira de pesquisar arquivos onde existem duas instâncias de palavras no mesmo arquivo. Eu tenho usado o seguinte para realizar minhas pesquisas até este ponto:
find . -exec grep -l "FIND ME" {} \;
O problema que encontro é que, se não houver exatamente um espaço entre "FIND" e "ME", o resultado da pesquisa não produzirá o arquivo. Como adaptar a cadeia de pesquisa anterior, onde as palavras "FIND" e "ME existem em um arquivo em oposição a" FIND ME "?
Estou usando o AIX.
grep -E
/egrep
que descreve todos os padrões que você está interessado em (e usando+
em vez de;
se seu achado tem suporte para+
.Respostas:
Com as ferramentas GNU:
Você pode fazer normalmente:
Mas isso executaria dois greps por arquivo. Para evitar a execução de muitos se
grep
ainda ser portátil, enquanto permite qualquer caractere nos nomes de arquivo, você pode:A ideia é converter a saída de
find
para um formato adequado para xargs (que espera um espaço em branco (SPC / TAB / NL e os outros espaços em branco do seu código do idioma com algumas implementações dexargs
)) lista separada de palavras em que aspas simples e duplas e barras invertidas podem espaços em branco de escape e um ao outro).Geralmente, você não pode pós-processar a saída de
find -print
, porque ela separa os nomes de arquivo com um caractere de nova linha e não escapa aos caracteres de nova linha encontrados nos nomes de arquivo. Por exemplo, se vemos:Não temos como saber se é um arquivo chamado
b
em um diretório chamadoa<NL>.
ou se são os dois arquivosa
eb
.Ao usar
.//.
, porque//
não pode aparecer de outra maneira no caminho de um arquivo como resultado defind
(porque não existe um diretório com um nome vazio e/
não é permitido em um nome de arquivo), sabemos que, se virmos uma linha que contenha//
, isso será a primeira linha de um novo nome de arquivo. Portanto, podemos usar esseawk
comando para escapar de todos os caracteres de nova linha, exceto daqueles que precedem essas linhas.Se pegarmos o exemplo acima,
find
seria exibido no primeiro caso (um arquivo):Qual awk escapa para:
Então, isso
xargs
é visto como um argumento. E no segundo caso (dois arquivos):O
awk
que sairia como está, entãoxargs
vê dois argumentos.fonte
find ... -print0
e emgrep --null
vez disso?grep --null
(aka -Z) é usado no primeiro, mas é uma extensão GNU.-print0
(outra extensão GNU) não ajudaria aqui..//.
significa ainda, e me pergunto como posso modificar isso para aceitar um argumento da linha de comando, digamos$1
?-print0
comfind
e-0
comxargs
?find -print0
em nenhum lugar na minha resposta.Se os arquivos estiverem em um único diretório e seu nome não contêm espaço, tabulação, nova linha
*
,?
nem[
caracteres e não começar com-
, nem.
, isso irá obter uma lista de arquivos contendo ME, então restrita que até os que também contêm FIND.fonte
grep -l CategoryLinearAxis `grep -l labelJsFunction *`
procurar arquivos que tenham ambos os atributos. Que maneira perfeita de fazer isso. 1Com
awk
você também pode executar:Ele usa
cx
ecy
conta para as linhas correspondentesFIND
e respectivamenteME
. NoEND
bloco, se ambos os contadores> 0, ele imprime oFILENAME
.Isso seria mais rápido / mais eficiente com
gnu awk
:fonte
Ou use
egrep -e
ougrep -E
assim:find . -type f -exec egrep -le '(ME.*FIND|FIND.*ME)' {} \;
ou
find . -type f -exec grep -lE '(ME.*FIND|FIND.*ME)' {} +
O
+
make find (se suportado) adiciona vários nomes de arquivo (caminho) como argumentos ao comando que está sendo-exec
editado. Isso salva processos e é muito mais rápido do que o\;
que invoca o comando uma vez para cada arquivo encontrado.-type f
corresponde apenas aos arquivos, para evitar grepping em um diretório.'(ME.*FIND|FIND.*ME)'
é uma expressão regular que corresponde a qualquer linha que contenha "ME" seguido de "FIND" ou "FIND" seguido de "ME". (aspas simples para impedir que o shell interprete caracteres especiais).Adicione
-i
a aogrep
comando para torná-lo sem distinção entre maiúsculas e minúsculas.Para corresponder apenas às linhas em que "FIND" vem antes de "ME", use
'FIND.*ME'
.Para exigir espaços (1 ou mais, mas nada mais) entre as palavras:
'FIND +ME'
Para permitir espaços (0 ou mais, mas nada mais) entre as palavras:
'FIND *ME'
As combinações são infinitas com expressões regulares e, desde que você esteja interessado em corresponder apenas linha por vez, o egrep é muito poderoso.
fonte
find
na pergunta.Olhando para a resposta aceita, parece mais complexa do que precisa ser. Versões GNU de
find
egrep
exargs
apoio strings terminadas em nulo. É tão simples quanto:Você pode modificar seu
find
comando para filtrar os arquivos desejados e funciona com nomes de arquivos que contêm qualquer caractere; sem a complexidade adicional desed
análise. Se você deseja processar ainda mais os arquivos, adicione outro--null
até o últimogrep
E, como uma função:
Obviamente, use a resposta aceita se você não estiver executando versões GNU dessas ferramentas.
fonte
--null
,--print0
,-0
São todas as extensões GNU. Embora alguns deles sejam encontrados em outras implementações hoje em dia, eles ainda não são portáteis e não estão no padrão POSIX ou Unix.