grep comportamento estranho com palavras de uma letra

10

Estou removendo palavras de parada de um texto, usando aproximadamente este código

Eu tenho o seguinte

$ cat file
file
types
extensions

$ cat stopwords
i
file
types

grep -vwFf stopwords file

Estou esperando o resultado: extensions

mas recebo o (acho incorreto)

file
extensions

É como se a palavra filetivesse sido ignorada no arquivo de palavras irrelevantes. Agora aqui é a parte legal: se eu modificar o arquivo de stopwords, mudando a palavra / única letra ina primeira linha, para qualquer outra letra ascii para além de f, i, l, e, em seguida, o mesmo comando grep me dá um resultado diferente e correcta extensions.

O que está acontecendo aqui e como corrigi-lo?

Estou usando o grep (BSD grep) 2.5.1-FreeBSD em um Mac OSX GNU bash, versão 4.4.12 (1)

Tim
fonte
Você pode usar a -xopção para regex de linha em vez de -wpara word? No entanto, acho que a -Fopção cancelará qualquer um deles ou vice-versa.
jesse_b
grep (GNU grep) 3.1 funciona como o esperado.
Hauke ​​Laging
Eu repliquei isso. Outro dado: tornar o ipadrão o segundo e não o primeiro padrão no stopwordsarquivo também altera o comportamento.
JdeBP #
Não consigo reproduzir o comportamento no OpenBSD 6.2 com o nativo grepnem com o GNU grep3.1.
Kusalananda

Respostas:

13

Isso foi um problema bsdgrep, relacionado a uma variável que rastreia a parte da linha atual ainda a ser varrida e substituída por chamadas sucessivas ao mecanismo de correspondência de expressões regulares quando vários padrões estão envolvidos.

correção local

Você pode contornar isso até certo ponto, não usando a -wopção, que depende dessa variável para a operação correta e, portanto, está falhando, mas usando as extensões de expressão regular que correspondem ao início e ao final das palavras, fazendo com que seu stopwordsarquivo se pareça com:

\ <i \>
\ <arquivo \>
\ <tipos \>

Esta solução alternativa também exigirá que você não use a -Fopção

Observe que os componentes de expressão regular documentados[[:<:]] e [[:>:]]que o re_formatmanual informa não funcionarão aqui. Isso ocorre porque a biblioteca de expressões regulares compilada bsdgreptem o suporte à compatibilidade de expressões regulares GNU ativado. Este é outro bug, que foi consertado.

correção de serviço

Este bug foi corrigido no início deste ano. A correção ainda não chegou aos sabores STABLE ou RELEASE do FreeBSD, mas está em ATUALIZAÇÃO.

Para colocar isso na versão MacOS grepderivada do FreeBSD bsdgrep, consulte a Apple. ☺

Leitura adicional

JdeBP
fonte
Bom, e obrigado por relatar isso a montante. Eu acharia esta resposta ainda mais fascinante se citasse o código do buggy.
dhag
1

Este código:

pl " Input data file data1 and stopwords file data2:"
head data1 data2

pl " Expected output:"
cat $E

pl " Results, grep:"
# grep -vwFf stopwords file
grep -vwFf data2 data1

pl " Results, cgrep:"
cgrep -x1 -vFf data2 data1

produz:

-----
 Input data file data1 and stopwords file data2:
==> data1 <==
file
types
extensions

==> data2 <==
i
file
types

-----
 Expected output:
extensions

-----
 Results, grep:
file
extensions

-----
 Results, cgrep:
extensions

Em um sistema como:

OS, ker|rel, machine: Apple/BSD, Darwin 16.7.0, x86_64
Distribution        : macOS 10.12.6 (16G29), Sierra
bash GNU bash 3.2.57

Mais detalhes sobre o cgrep, disponível via brew e no sourceforge:

cgrep   shows context of matching patterns found in files (man)
Path    : ~/executable/cgrep
Version : 8.15
Type    : Mach-O64-bitexecutablex86_64 ...)
Home    : http://sourceforge.net/projects/cgrep/ (doc)

Saúde, drl

drl
fonte
acabei de receber um novo grep.
Tim
@ Tim - Espero que você ache o cgrep tão útil quanto eu. A velocidade dos testes que fiz comparou-a com o GNU grep e os recursos "context / windowing" são muito úteis. Ele também constrói facilmente em sistemas Linux ... elogios, drl
drl