Detectando padrão no final de uma linha com grep

65

Se eu fizer:

$ ls -R
.:
4Shared/  Cloud/

./4Shared:
UFAIZLV2R7.part3.rar

./Cloud:
UFAIZLV2R7.part2.rar.part
UFAIZLV2R7.part1.rar.part
UFAIZLV2R7.part4.rar.part

Se eu quiser listar .rarapenas os arquivos e usar grep , ele também mostrará os .rar.partarquivos, o que não é o meu desejo.
Estou resolvendo isso usando findou ls **/*.rarconforme descrito neste tópico e eles funcionam bem, mas gostaria de saber se é possível fazer isso via grep.

Eu tentei (pensando sobre EOL):

ls -R | grep ".rar\n"

sem resultados.
Eu acho que o problema está em descobrir se o greping é encontrado no final da linha , mas não tenho certeza.

Alguma ajuda aqui, por favor?

Sopalajo de Arrierez
fonte
Por que você gostaria de usar grepneste caso? Por que não find?
devnull
11
@ devnull, saber como detectar padrões que estão apenas no final de uma linha pode ser útil em muitos casos. Por exemplo: portabilidade, uso em roteadores com Linux simplificado demais, uso com UnxUtils for Windows (seu findcomando está em conflito com o Windows) e ... aprendendo ;-). A questão não é sobre "Arquivos de Listagem em um dir" (que é apenas um exemplo costume), mas sim "Compreender o uso do comando grep"
Sopalajo de Arrierez
11
honestamente, se você está contando com o final de uma linha como seu separador, deve usá-lo ls -1R.
precisa saber é o seguinte
11
E você nem precisa grep. Veja minha resposta.
precisa saber é o seguinte
@mikeserv, o que poderia acontecer sem a -1Rchave. Aparentemente, os resultados são os mesmos.
Sopalajo de Arrierez

Respostas:

89

A $âncora corresponde ao final de uma linha.

ls -R | grep '\.rar$'

Você também pode usar findpara isso:

find . -name '*.rar'
jordanm
fonte
Eu não percebi o "." precisa ser escapado no grep. É tratado como um curinga?
thebunnyrules
11
@thebunnyrules "." em regex significa um de qualquer caractere.
jordanm
10

Além da sua pergunta, observe que .rarnão apenas corresponde a ".rar", mas também a todos os caracteres (inclusive .) antes do rar. Nesse caso, provavelmente não é um problema, mas .deve ser escapado em regexes.

ls -R | grep "\.rar$"
Hauke ​​Laging
fonte
Você quis dizer que .ascé como *ascpadrão? Por isso, corresponderá, por exemplo whereverasc,.
Sopalajo de Arrierez
2
@SopalajodeArrierez Não, ele não corresponde a todos os grupos de caracteres, mas a todos os caracteres, por exemplo xrar.
precisa saber é o seguinte
5

Você também pode instruir grepa procurar sua string começando em um limite de palavras. A .é um desses limites.

$ ls -R | grep '\brar$'

Exemplo

Digamos que eu tenho esses dados de amostra.

$ ls -1
afile.rar
xrar
UFAIZLV2R7.part1.rar.part
UFAIZLV2R7.part2.rar.part

Este comando encontraria apenas o arquivo com a .rarextensão.

$ ls -R | grep '\brar$'
afile.rar

Como isso funciona?

O metacaractere \bé uma âncora como o sinal de intercalação e o cifrão. Corresponde em uma posição chamada "limite de palavras". Esta partida tem comprimento zero.

Situações em que isso não funcionará

Se você tiver arquivos nomeados, blah-raresses também serão detectados.

$ ls -R | grep '\brar$'
afile-rar
afile.rar

Isso ocorre porque caracteres que não sejam alfanuméricos são normalmente considerados caracteres de limite e, portanto, passariam por essa abordagem.

slm
fonte
Parece ser o mesmo à primeira vista, mas é um pouco diferente, de fato. Obrigado, @slm. Incomoda se eu usar aspas duplas em "vez de aspas simples?
Sopalajo de Arrierez
11
@SopalajodeArrierez - o nope funciona de qualquer maneira. Isso encontrará todos os arquivos que podem ser nomeados começando com w .rar. Mas estes não serão um problema com o uso de ls -R. Somente se você tiver usado ls -Ra.
Slm
Um de vocês estaria interessado em explicar essa pequena diferença ao público?
precisa saber é o seguinte
@HaukeLaging A -Popção para grepno meu exemplo. Isso desencadeia a interpretação PCRE do argumento.
Slm
11
@SopalajodeArrierez - se um arquivo contiver um caractere de nova linha ( \n), que é um caractere legal. O ls -1Rforçará os arquivos a serem exibidos em uma única coluna independentemente.
Slm
0

Apenas faça :

ls -1R -I"?" -I"??" -I"???" -I"*[!.][!r][!a][!r]"

Você não precisa de grepnada.

NOTA: O acima funciona ... exceto que ainda recebe pelo menos afile-rar e eu não entendo o porquê. Vou deixar aqui, mas não tenho orgulho disso. De qualquer forma, como outros já disseram:

find . '*.rar'
mikeserv
fonte
Isso não bloqueou arquivos nomeados xrarou afile-rar.
Slm
Ainda estou recebendo os outros arquivos na saída.
Slm
@slm Que outros arquivos? Eu acho que pode ser porque eles são muito curtos. Eu só notei isso. Eu consertei isso também.
precisa saber é o seguinte
Os arquivos afile-rare xrarainda estão sendo incluídos na saída. Nenhuma alteração nos seus mods mais recentes também. Problema traquina não? É divertido tentar resolvê-lo sem os métodos regulares 8-)
slm
@ slm Sim, é por isso que venho aqui. Eu não entendo por que isso acontece -dash. A xrarcoisa que eu poderia segurar, mas não o -dash.que eu não entendo o-dash.
mikeserv
0

Use aspas simples para fazer o $ funcionar como fim de linha. Se você deseja grep com alguma variável também, use a combinação de aspas duplas e simples como abaixo:

grep "$var"'$'

Minha postagem anterior foi excluída, dizendo que é duplicada. Deixe-me explicar como isso é diferente.

As outras postagens mencionam o uso completo de aspas duplas ""ou o uso completo de aspas simples ''. Ambos têm suas próprias limitações. A seguir explica.

O problema com todas as aspas duplas é o seguinte: grep "pattern$"fornece o seguinte erro:Illegal variable name.

E usar todas as aspas simples funciona, mas se você deseja substituição de variável, todas as aspas simples não funcionarão. Por exemplo:

Se eu tiver uma string A_BOOK, incluindo outras strings em um arquivo FILE.

$ cat FILE
A_BOOK
B_BOOK_NOT_LAST
C_BOOK

Se eu definir o BOOK como uma variável BK

set BK = BOOK

Se eu grep com todas as aspas duplas, recebo o seguinte erro:: grep "${BK}$" FILE*1st $ para substituição de variável, 2nd para final de padrão ( nome ilegal da variável ).

Se eu grep com todas as aspas simples, a substituição da variável não acontece. grep '${BK}$' FILEnão retorna nada

Se eu usar uma combinação de aspas duplas e simples, recebo o que espero. Aspas duplas para substituição de variável e as aspas simples para o final do padrão.

$ grep "${BK}"'$'  # << gives expected output
A_BOOK
C_BOOK
user274900
fonte
Parece que você está usando csh. A "foo$"sintaxe funciona bem com sh e family.
Olorin
Sim Olorin. Estou usando o tcsh. Obrigado por apontar isso.
user274900
0

Se depois de seguir o descrito acima e nada funcionar, pode ser devido ao final da linha. Para corrigir, faça: dos2unix pr0n.txte faça o seu grepnovamente.

typelogic
fonte