Supondo que você queira dizer caractere em vez de letra (como em, você também deseja excluir linhas que contenham ...
ou 11
, embora .
ou 1
não sejam letras):
grep -vx -e '' -e '\(.\)*'
ou:
grep -vx '\(\(.\)*\)\{0,1\}'
Isso é remover ( -v
) linhas ou linhas vazias que começam com um caractere ( .
) seguido pelo mesmo caractere ( sendo uma referência anterior ao que foi capturado por
\(...\)
) repetido 0 ou mais vezes ( *
) até o final da linha ( -x
ancora o padrão no início e no final da linha).
Portáteis, você não pode usar egrep
ou grep -E
aqui, pois os EREs padrão não têm referências anteriores (somente os BREs).
Para linhas que contêm pelo menos duas letras diferentes, ignorando os outros tipos de caracteres (usaremos [[:alpha:]]
aqui para letra , ou seja, qualquer caractere considerado alfabético na sua localidade):
grep -vx '[^[:alpha:]]*
[^[:alpha:]]*\([[:alpha:]]\)\([^[:alpha:]]*\)*[^[:alpha:]]*'
(em duas linhas, que é outra maneira de passar dois padrões diferentes). Ou:
grep -vx '[^[:alpha:]]*\([^[:alpha:]]*\([[:alpha:]]\)\([^[:alpha:]]*\)*[^[:alpha:]]*\)\{0,1\}'
Essa pessoa removeria linhas como 12345aaa
(apenas uma letra) ou -+-+-+-
(nenhuma letra).
Se você quiser excluir Aaaa
linhas também (caso ignorar quando comparar letras), adicione a opção -i
.
Note que ele funciona no nível do personagem, então ele pode não fazer o que você espera se houver grafemas expressos com mais de um caractere. Por exemplo, ele excluiria uma linha como essa por:
$ printf 'e\u0300e\u0301\n'
èé
(assumindo o GNU printf
ou compatível), mas não um como:
$ printf '\ue8\ue9\n'
èé
(onde e\u300
é a forma decomposta e \ue8
da forma pré-composta da è
grapheme; e
(U + 0065) e è
(U + 00E8) são alfabéticos , mas não o U + 0300 ou U + 0301 combinando acentos graves / agudos).
Para trabalhar com grafemas, você pode usar pcregrep
ou GNU grep
com a opção -P
:
Para o primeiro caso (pelo menos dois clusters de grafema diferentes):
grep -vxP '(?:(\X)*)?'
Para o segundo caso (pelo menos dois clusters de grafemas letter ):
grep -vxP '(?:(?=\PL)\X)*(?:((?=\pL)\X)(?:(?:(?=\PL)\X)*(?!\pM))*(?:(?=\PL)\X)*)?'
Em que (?=\PL)\X
é um cluster de grafema sem letras (um cluster de grafema ( \X
) forneceu (?=...)
, inicia com um cluster de letra não grafada ( \PL
) e (?=\pL)\X
a letra grafite.
\pL
corresponde ao Carta unicode corretamente. Ao contrário da classe de caracteres [:alpha:]
POSIX, também inclui letras de scripts não alfabéticos.
Note que ele consideraria e\u300\u301
, e\u301\u300
, \ue9\u300
, \ue8\u301
como quatro grupos diferentes, embora todos fossem e
com sotaque agudo e grave.
Tenha também cuidado com caracteres como ffi
(U + FB03) que contêm várias letras em um caractere .
Com o PCRE, você também pode usar abordagens positivas :
-
pelo menos 2 caracteres diferentes:
grep -P '(.).*(?!).'
-
pelo menos 2 caracteres de letras diferentes:
grep -P '(\pL).*(?!)\pL'
-
pelo menos 2 clusters de grafema diferentes:
grep -P '^\X*(\X)\X*(?!(?!\pM))\X'
aquele não funcionaria adequadamente com o Corão Hangul em forma decomposta (pelo menos). PCRE (ao contrário do RE de
perl
com\b{g}
) não tem operador de limite de grafema (AFAIK) e tem suporte limitado para propriedades unicode. Estamos usando(?!\pM)
(o que significa nesse contexto: "desde que não seja seguido por um caractere de combinação de caracteres") como uma aproximação, mas isso não funciona para letras Hangul de várias partes / sílaba caracteres em que as partes não têm essa propriedade. Ele excluiria려련련
, por exemplo. Agora também podemos argumentar que cada parte é uma letra ...Com
perl
5,22 ou acima, você pode escrevê-lo:perl -Mopen=locale -lne 'print if /\b{g}(\X).*\b{g}(?!\b{g})\X/'
-
pelo menos 2 diferentes conjuntos de grafos letter :
grep -P '^\X*((?=\pL)\X)\X*(?!(?!\pM))(?=\pL)\X'
Novamente, não funciona em
려련련
. Comperl
:perl -Mopen=locale -lne 'print if /\b{g}(?=\pL)(\X).*\b{g}(?!\b{g})(?=\pL)\X/'
Com perl
, podemos usar abordagens mais simples, como:
-
pelo menos 2 caracteres diferentes:
perl -Mopen=locale -MList::MoreUtils=uniq -lne ' print if uniq(/./g) >= 2'
-
pelo menos 2 caracteres de letras diferentes:
perl -Mopen=locale -MList::MoreUtils=uniq -lne ' print if uniq(/\pL/g) >= 2'
-
pelo menos 2 clusters de grafema diferentes:
perl -Mopen=locale -MList::MoreUtils=uniq -lne ' print if uniq(/\X/g) >= 2'
-
pelo menos 2 diferentes conjuntos de grafos letter :
perl -Mopen=locale -MList::MoreUtils=uniq -lne ' print if uniq(grep /^\pL/, /\X/g) >= 2'