Qual é a natureza do comando grep?

Qual é a natureza do comando grep?

Eu queria usar o grep em todos os arquivos .txt usando o caractere curinga '*'.
Tentei este comando (e também sem as aspas " "), mas falhei.

ls | grep "*.txt"

O interessante é que se eu colocar outro caractere no comando grep correspondente a um arquivo .txt do diretório, funciona

>>ls | grep s*.txt
sample.txt

Eu sei que ls *.txtvai funcionar, mas fiquei um pouco surpreso com a natureza do comando grep. Alguém poderia me ajudar por que isso está acontecendo?

É porque o grep usa expressões regulares, por favor ajude.

Responder1

Em regexes, *significa "qualquer número do item anterior", e não "qualquer número de caracteres", como acontece nos padrões de shell. E .significa "qualquer caractere único". Então, para procurar por "qualquer coisa, seguida de literal .txt", você usaria .*\.txt. Ou apenas \.txt, já que normalmente as correspondências de regex procuram a correspondência em qualquer lugar da linha. Então, novamente, \.txttambém corresponderia a um nome de arquivo como foo.txtgz, já que .txtnão precisaria estar no final. Você precisaria \.txt$bloquear o padrão até o final da linha.

A regex *.txtnão tem sentido, é um erro ou procura um asterisco literal, dependendo da implementação e se você estiver usando regexes básicas ( grep) ou regexes estendidas ( grep -E). Melhor não usar.

Por outro lado, s*.txtprocuraria "qualquer número de letras s, depois qualquer caractere único e depois literal txt". Essa é uma regex mais válida, mas... ainda não corresponde sample.txt.

Em vez disso, o que acontece no seu segundo comando é que, como s*.txtnão está entre aspas, o shell expande o s*.txtantes grepde vê-lo. Se o único arquivo correspondente for sample.txt, grepprocure-o na saída de ls. (Se houvesse vários nomes de arquivos correspondentes, o primeiro seria considerado o padrão e o restante como nomes de arquivos para grepleitura. Nesse caso, a entrada do canal seria ignorada.)


Mas lstambém pode levar uma lista de arquivos, então, embora você possa usar

ls | grep '\.txt'

para obter qualquer .txtarquivo, provavelmente seria mais fácil usar

ls *.txt 

em vez de.

Responder2

É em parte porque grepusa expressões regulares (na verdade, é isso que reo nome significa - é a abreviação deglobalRnormaleexpressãoprinte).

O *curinga em expressões regulares é diferente do *curinga no shell globbing.

Em expressões regulares, *significa "zero ou mais do objeto definido anteriormente". No entanto, .étambémum curinga, que significa 'um caractere'.

Em shell globs, *significa "zero ou mais caracteres". .não é um curinga.

Quando você grepprocura o padrão "*.txt", procura zero ou mais de qualquer coisa, seguido por exatamente mais um caractere, seguido pela string literal txt.

Quando você grepusa o padrão "s*.txt"m you are looking for a literals , followed by zero or moretxt` s, followed by any character, followed by the literal string.

É por isso que uma coisa comum que você encontrará em expressões regulares é .*, que significa "um de qualquer caractere seguido por zero ou mais de qualquer caractere". Regexese para "literalmente qualquer combinação de caracteres diferente de zero caracteres".

Quando você ls *.txtestiver dizendo ao shell "Encontre quaisquer nomes de arquivos que correspondam ao padrão glob *.txt, liste-os aqui e forneça-os como argumentos para o lscomando.

Responder3

observe que grep está pesquisando arquivocontenteenquanto o primeiro argumento é search PATTERN e outros argumentos interpretados como FILES para examinar

fica mais claro para você ao usar grep -H -osinalizadores ou colocá-lo grepdentro de um script e executá-lo bash -x scriptpara ver como os globs do shell se expandiram antes de serem passados ​​​​como argumentos

informação relacionada