grep comando para exibir todas as linhas que começam e terminam com o mesmo caractere

8

Eu quero saber como usar grep para exibir todas as linhas que começam e terminam com o mesmo caractere.

    
por Nayan Jariwala 21.09.2016 / 10:55

4 respostas

14

POSIXly:

pattern='\(.\).*
.'
grep -x -- "$pattern" file

Não funcionará se a linha começar ou terminar com caractere de byte inválido; se você quiser cobrir esse caso, poderá adicionar LC_ALL=C , embora LC_ALL=C trabalhe somente com dados de caractere de byte único.

perl6 parece ser a melhor ferramenta, se você 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 alterará seu texto, transformando-o em NFC form:

$ 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 string em NFG form (representa Normalization Form Grapheme ), que é perl6 inventado para lidar corretamente com graphemes não pré-compostos:

$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.chars.say'
1
$ printf '\u0044\u0323\u0307\n' | perl6 -ne '.codes.say'
2
    
por 21.09.2016 / 11:06
10

Não grep mas awk:

awk -F "" 'NF && $1 == $NF'

Esses casos especiais são tratados:

  • não imprime linhas vazias
  • sempre imprime linhas de 1 caractere

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 em as implementações de awk derivaram do original por A, W e K como em BSDs e Unices comerciais. Mais portátil, mas mais para digitar:

awk '/./ && substr($0,1,1) == substr($0,length)'
    
por 21.09.2016 / 11:08
8
grep -xe '\(.\).*' -e .

Exemplo:

$ printf '%s\n' il y était cet été  | grep -xe '\(.\).*' -e .
y
été

-x é para correspondência exata (correspondência na linha inteira). sendo uma referência inversa ao caractere capturado em \(.\) . Adicionamos um -e . para cuidar do caso especial de uma linha contendo um único caractere.

Ele supõe que a entrada contém texto válido na localidade atual.

A correspondência está no caractere , não byte (os que estão em UTF-8 são os dois bytes 0xc3 0xa9 por exemplo), nem em graphem cluster > (não funcionaria se estes fossem escritos em sua forma decomposta com e seguido do U + 0301 combinando acento agudo, por exemplo).

Para trabalhar em clusters de graphem, com um grep que suporta -P para PCRE:

$ printf 'e\u0301te\u0301\n' | grep -xPe '(\X).*|\X'
été

Isso pressupõe que a decomposição é a mesma para os dois clusters, 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).*$/'
ḉ blah ḉ
    
por 21.09.2016 / 13:04
1

Alternativa rápida do 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$
    
por 21.09.2016 / 12:24