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!

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.


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.


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.


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.


Isso não corresponderá a étudetodos, porque o caractere ASCII correspondente ao acento irá atrapalhar a regex.
Alex
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.