Por que a $ anchor de fim de linha não está funcionando com o comando grep, mesmo que a âncora de front-of-line seja?

13

Muito novo no UNIX, mas não é novo na programação. Usando o Terminal no MacBook. Para fins de gerenciamento e pesquisa de listas de palavras para construção de palavras cruzadas, estou tentando ser útil com o comando Grep e suas variações. Parece bastante simples, mas ficar preso no início com o que eu pensei que deveria ser um caso simples.

Quando eu entro

grep "^COW" masternospaces.txt

Eu obtenho o que quero: uma lista de todas as palavras que começam com COW.

Mas quando eu entro

grep "COW$" masternospaces.txt

Espero obter uma lista de palavras que terminem com COW (existem muitas dessas palavras) e nada é retornado.

O arquivo é um arquivo de texto simples, com todas as linhas apenas uma palavra (ou uma frase de palavra sem espaços) em letras maiúsculas.

Alguma ideia do que poderia estar acontecendo aqui?

    
por DTalvacchio 29.12.2014 / 19:56

5 respostas

16

Como o @steeldriver mencionou, o problema provavelmente é causado por um estilo de finalização de linha diferente do que o que o grep está esperando.

Para verificar os finais da linha

Você pode usar hexdump para verificar exatamente como seus finais de linha são formatados. Eu sugiro que você use meu formato favorito:

hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt

Com a saída, verifique os finais da linha: 0a - > LF , 0d - > %código%. Um exemplo muito rápido daria algo assim:

$ hexdump -e '"%08_ad (0x%08_ax)    "8/1 "%02x ""   "8/1 "%02x "' -e '"    "8/1 "%_p""|"8/1 "%_p""\n"' masternospaces.txt
00000000 (0x00000000)    4e 6f 20 43 4f 57 20 65   6e 64 69 6e 67 0d 0a 45    No COW e|nding..E
00000016 (0x00000010)    6e 64 69 6e 67 20 69 6e   20 43 4f 57 0d 0a          nding in| COW..

Observe os finais de linha no formato dos: CR .

Para alterar os finais da linha

Você pode ver aqui ou aqui para vários métodos de alteração de finais de linha usando várias ferramentas, mas para uma coisa de uma só vez, você sempre pode usar o vi / vim:

vim masternospaces.txt
:set fileformat=unix
:wq

Para grep sem alterar nada

Se você quiser que 0d 0a corresponda, não importa o término da linha, você sempre poderá especificar finais de linha como este:

grep 'COW[[:cntrl:]]*$' masternospaces.txt

Se uma linha em branco for exibida, você poderá verificar se realmente combinou algo usando a opção grep de -v :

grep 'COW[[:cntrl:]]*$' masternospaces.txt | cat -v

Meu favorito pessoal

Você também pode grep e padronizar a saída usando cat :

sed -n '/COW^M*$/{;s/^M//g;p;};' masternospaces.txt

onde sed é obtido digitando ^M no seu teclado.

Espero que isso ajude!

    
por 29.12.2014 / 23:43
1

Embora você possa usar a sintaxe RegEx 'padrão' com o grep (como na resposta @ user43791 ), o grep também tem outros identificadores para significar os limites de entrada.

Os correspondentes para o início e o final da linha inteira são \' (backtick) (em vez de ^ ) e \' (apóstrofo) (em vez de $ ).

Então, para o seu comando original, você usaria: grep "COW\'" masternospaces.txt

Nota: Também é importante observar que ? e + serão tratados literalmente, a menos que você os escape usando \? e \+ para torná-los seus correspondentes no estilo RegEx.

Fonte: grep sintaxe de expressão regular

    
por 05.05.2017 / 03:11
0

Outra maneira de remover o \r antes do grep:

... | dos2unix | egrep 'COW$' | ...

Eu gosto disso, é muito claro, pois não lembro de coisas como [[:cntrl:]] por muito tempo.

    
por 12.07.2018 / 19:56
-2

"COW $" Quando pararameter de bash para grep, foi interpretado como 'COW', onde tratamos "$" como "", porque $ é um simbol de escape. quando nada foi estimado por $, é interpretado como string vazia por shell bash então você deve usar  grep 'COW $' masternospaces.txt em vez de.

    
por 30.11.2017 / 18:10
-3

No BSD grep você precisa escapar "$" e colocar sua string entre aspas duplas:

"COW\$"
    
por 28.06.2018 / 04:47

Tags