Como dizer “grep -w” quais caracteres compõem “palavras”?

7
$ printf 'asf .test. afd\nasaf foo-test asfdads\n'
asf .test. afd
asaf foo-test asfdads

$ printf 'asf .test. afd\nasaf foo-test asfdads\n' | grep -w test
asf .test. afd
asaf foo-test asfdads

Pergunta : Como posso corresponder ao "teste foo"? Para ser mais preciso, como posso dizer "-w" use "-" como separador, mas não use "." ?

Ou, em outras palavras, posso dizer a grep que . está entre os caracteres que compõem palavras e, portanto, que não há limite de palavras entre . e test ?

Ou existem outras soluções além do grep?

    
por freaking-good-question 24.04.2015 / 17:43

1 resposta

10

Nas versões anteriores a 2.19, o grep do GNU -w só consideraria alnums de caracteres de byte único e sublinhado (portanto, em locales UTF-8, apenas 26 + 26 + 10 + 1 (letras ASCII, dígitos) e sublinhado)) como constituintes de palavras. Então, por exemplo, echo Stéphane | grep -w St corresponderia. Isso foi corrigido em 2,19.

No entanto, você pode implementar a lógica manualmente:

 grep -E '([^[:alnum:]_.]|^)test([^[:alnum:]_.]|$)'

Isso é test precedido por um não-constituinte de palavras ou o início da linha e seguido por um não constituinte de palavras ou o fim da linha.

(acima de [:alnum:] corresponde a dígitos e letras em sua localidade, não apenas em ASCII, corrija a localidade para C se desejar apenas ASCII).

Se você não quer que aqueles componentes que não sejam a palavra sejam incluídos na correspondência (por exemplo, porque você está usando o -o do GNU), você pode, desta vez, usar os operadores CPEX e look-around:

grep -Po '(*UCP)(?<![\w.])test(?![\w.])'

Remova (*UCP) e adicione LC_ALL=C para corresponder apenas a letras e dígitos ASCII.

Usar (*UCP) no início de um regexp informa à biblioteca PCRE que U̲niC̲ode P̲roperties devem ser usados para \w .

Sem ele, \w corresponderia aos alfanuméricos e sublinhados do seu idioma, mas apenas aos caracteres de byte único. Isso não funcionaria nas localidades UTF-8 (a norma hoje em dia), onde apenas as ASCII seriam correspondidas. (*UCP) faz com que funcione para o UTF-8 também. Ele combinaria com base na própria noção de propriedade de caracteres do PCRE, que pode ser diferente da sua localidade, mas nos sistemas GNU, isso é tão bom quanto as definições de localidade UTF-8 estão incompletas e desatualizadas (pelo menos a partir de 2015-04).

    
por 24.04.2015 / 18:07