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.