Quero saber como usar greppara exibir todas as linhas que começam e terminam com o mesmo caractere.
Quero saber como usar greppara 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=Cfuncione 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 perl6o texto será alterado, transformando-o em NFCforma:
$ 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, perl6armazena a string no NFGformulário (stand for Normalization Form Grapheme), que é uma perl6maneira 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 NFGformulário ( Gfor Grapheme), que é uma perl6maneira 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, mawke busybox awk(bytes, não caracteres para os dois últimos), mas não é padrão e não funciona nas implementações awkderivadas 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)'
FScomo a string vazia não é padrão e não funcionará em alguma awkimplementação.
awk 'length&&substr($0,1,1)==substr($0,length)'(argumento padrão nota lengthé $0, e ação padrão é {print $0})
nawkque é 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). \1sendo 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 eseguidos pelo U + 0301 combinação de sotaque agudo, por exemplo).
Para trabalhar em clusters de graphem, com um grepsuporte -Ppara 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+0327não corresponderia a um expresso como c U+0327 U+0301ou ć( U+0107) U+0327ou ç( U+00E7) U+0301ou ḉ ( 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$