Quero saber como usar grep
para exibir todas as linhas que começam e terminam com o mesmo caractere.
Quero saber como usar grep
para exibir todas as linhas que começam e terminam com o mesmo caractere.
Respostas:
POSIXly:
pattern='\(.\).*\1
.'
grep -x -- "$pattern" file
Não funcionará se a linha começar ou terminar com um caractere de byte inválido; se você quiser cobrir esse caso, poderá adicionar LC_ALL=C
, embora LC_ALL=C
funcione apenas com dados de caracteres de byte único.
perl6
parece ser a melhor ferramenta, se você a tiver em sua caixa:
$ printf '\ue7\u301 blah \u107\u327\n121\n1\n123\n' |
perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
ḉ blah ḉ
121
1
Embora ainda engasgue com caracteres inválidos.
Observe que perl6
o texto será alterado, transformando-o em NFC
forma:
$ printf '\u0044\u0323\u0307\n' |
perl6 -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+1e0c
U+0307
U+000a
$ printf '\u0044\u0323\u0307\n' |
perl -pe '' |
perl -CI -ne 'printf "U+%04x\n", ord for split //'
U+0044
U+0323
U+0307
U+000a
Internamente, perl6
armazena a string no NFG
formulário (stand for Normalization Form Grapheme
), que é uma perl6
maneira inventada de lidar adequadamente com grafemas não pré-compostos:
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.chars.say'
1
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.codes.say'
2
perl6
, embora o texto seja alterado (gire-o para NFC (formulário de normalização "composto")).
perl6
é armazenada no NFG
formulário ( G
for Grapheme
), que é uma perl6
maneira de lidar adequadamente com grafemas não pré-compostos.
Não grep, mas awk:
awk -F "" 'NF && $1 == $NF'
Esses casos especiais são tratados:
Um FS vazio divide o registro em um caractere por campo em gawk
, mawk
e busybox
awk
(bytes, não caracteres para os dois últimos), mas não é padrão e não funciona nas implementações awk
derivadas do original por A, W e K, como nos BSDs e nos escritórios comerciais. Mais portátil, mas mais para digitar:
awk '/./ && substr($0,1,1) == substr($0,length)'
FS
como a string vazia não é padrão e não funcionará em alguma awk
implementação.
awk 'length&&substr($0,1,1)==substr($0,length)'
(argumento padrão nota length
é $0
, e ação padrão é {print $0}
)
nawk
que é quase tão ruim :-)
grep -xe '\(.\).*\1' -e .
Exemplo:
$ printf '%s\n' il y était cet été | grep -xe '\(.\).*\1' -e .
y
été
-x
é para correspondência exata (correspondência em toda a linha). \1
sendo uma referência ao personagem capturado em \(.\)
. Nós adicionamos a -e .
para cuidar do caso especial de uma linha que contém um único caractere.
Ele assume que a entrada contém texto válido no código do idioma atual.
A correspondência está no caractere , não no byte (aqueles que estão em UTF-8 são os dois bytes 0xc3 0xa9, por exemplo), nem no cluster graphem (não funcionaria se aqueles fossem escritos em sua forma decomposta e e
seguidos pelo U + 0301 combinação de sotaque agudo, por exemplo).
Para trabalhar em clusters de graphem, com um grep
suporte -P
para PCRE:
$ printf 'e\u0301te\u0301\n' | grep -xPe '(\X).*\1|\X'
été
Isso pressupõe que a decomposição é a mesma para os dois grupos, por exemplo, um ḉ
expresso como c
U+0301
U+0327
não corresponderia a um expresso como c
U+0327
U+0301
ou ć
( U+0107
) U+0327
ou ç
( U+00E7
) U+0301
ou ḉ ( U+1E09
). Para isso, você precisa fazer a verificação em um formulário normalizado:
$ printf '\ue7\u301 blah \u107\u327\n' |
perl -MUnicode::Normalize -C -ne '
print if /^\X$/ || NFC($_) =~ /^(\X).*\1$/'
ḉ blah ḉ
perl6
, então perl6 -ne '.say if m/^(.).*$0$/ || /^.$/'
deve fazer todos os trabalhos para você.
Alternativa rápida para python2:
python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt
Exemplo:
$ python -c 'import sys;[sys.stdout.write(l) for l in sys.stdin if len(l)>1 and l.rstrip("\n").endswith(l[0])]' < input.txt | cat -A
nathan$
ookie $
a line a$