Cadeia de caracteres correspondente com um número fixo de caracteres usando grep

9

Estou tentando encontrar todas as 6palavras da letra usando grep. Eu tenho atualmente:

grep "^.\{6\}$" myfile.txt 

No entanto, estou descobrindo que também estou obtendo resultados como: étuis, étude.

Eu suspeito que tem algo a ver com os símbolos acima do enas palavras acima.

Existe algo que eu possa fazer para garantir que isso não aconteça?

Obrigado pela ajuda!


fonte

Respostas:

4

grepA idéia de um personagem depende da localidade . Se você estiver em um código de idioma não Unicode e fizer a grep de um arquivo com caracteres Unicode, as contagens de caracteres não corresponderão. Se você echo $LANGvir o local em que está.

Se você definir as variáveis ​​de ambiente LC_CTYPEe / ou LANGcomo um valor que termina com ".UTF-8", obterá o comportamento correto:

$ cat data
étuis
letter
éééééé
$ LANG=C grep -E '^.{6}$' data
étuis
letter
$ LANG=en_US.UTF_8 grep -E '^.{6}$' data
letter
éééééé
$

Você pode alterar seu código de idioma para apenas um único comando, atribuindo a variável na mesma linha que o comando.

Com essa configuração, os caracteres de vários bytes são considerados caracteres únicos. Se você deseja excluir caracteres não-ASCII completamente, algumas das outras respostas têm soluções para você.


Observe que ainda é possível que as coisas quebrem, ou pelo menos não façam exatamente o que você espera, na presença de caracteres combinados . Você greppode tratar CARTA LATINA PEQUENA E + COMBINANDO CARACTERES ACIMA ACIMA de forma diferente da CARTA LATINA PEQUENA E COM AGUDA.

Michael Homer
fonte
se você usar ., algo como wăsd'sirá corresponder
cuonglm
'é um caractere que pode razoavelmente fazer parte de uma "sequência com um número fixo de caracteres".
Michael Homer
Talvez. E você deve definir ambos LC_CTYPEe LANG, algo como LC_CTYPE=en_US.UTF-8 LANG=en_USfalhará. Use LC_ALLpor segurança.
cuonglm
2

Tente o seguinte:

LC_ALL=C.UTF-8 grep -x '[_[:alnum:]]\{6\}' file

-xuse para combinar a linha inteira e definido pelo POSIX (consulte grep ).

Veja aqui uma boa explicação do que LC_ALLfaz. Você pode definir LANGou LC_CTYPEusar utf-8 para obter o mesmo comportamento. A ordem que afeta é LC_ALL=> LANG=> LC_CTYPE.

cuonglm
fonte
2

Com o GNU, grepquando construído com suporte para PCRE, você pode:

grep -Px '\X{6}'

Enquanto .corresponde a um personagem, \Xcorresponde a um ideograma / graphem.

Em um código de idioma UTF-8:

$ locale charmap
UTF-8
$ printf '\u00e9tuis\n\u00e9tudes\n' | grep -Px '\X{6}'
études
$ printf 'e\u0301tuis\ne\u0301tudes\n' | grep -Px '\X{6}'
études

Nesse último études, existem 7 caracteres, 8 bytes e 6 grafemas.

Stéphane Chazelas
fonte
Parece que não funciona: echo épée | grep -Px '\X{6}'ouputépée
cuonglm
@Gnouc, você precisa executá-lo em um local UTF-8 (se os éacima foram codificados em UTF-8).
Stéphane Chazelas
Oh, meus erros. Funciona com UTF-8.
cuonglm
0

Você pode tentar algo como:

grep "^[A-Za-z]\{6\}$" myfile.txt

ou se as palavras também puderem conter números, então:

grep "^[A-Za-z0-9]\{6\}$" myfile.txt

Basta adicionar qualquer caractere aos colchetes que você deseja, além desses.

Warwick
fonte
Isso não corresponderá a étudetodos, porque o caractere ASCII correspondente ao acento irá atrapalhar a regex.
Alex