Shell: Extrair o último caractere da linha

Com o comando cut é fácil extrair o primeiro, segundo ou qualquer outro caractere da linha. Porém, é preciso saber a posição exata deste caractere para informá-la ao cut.

$ echo abcdef | cut -c 1
a
$ echo abcdef | cut -c 2
b
$ echo abcdef | cut -c 3
c

E se você quiser extrair o último caractere, independente do tamanho da linha em questão?

A primeira solução é saber qual a posição exata deste último caractere. Supondo que a linha está guardada em uma variável, use o modificador # para obter o tamanho do conteúdo da variável, ou seja, o tamanho da linha.

$ linha="abcdef"
$ echo ${#linha}
6

Agora sim, você pode usar esse truque para obter o último caractere:

$ echo $linha | cut -c ${#linha}
f

Há ainda uma outra solução, que envolve pensar diferente. Em vez de contornar a limitação do cut apelando para a expansão de variáveis do shell, que tal modificar nosso problema para que ele se enquadre nas possibilidades do cut?

  • O problema: extrair o último caractere.
  • O cut: sabe extrair o primeiro caractere.
  • Solução: tem como fazer o último caractere ser o primeiro?

O comando rev inverte a linha, fazendo com que o último caractere seja o primeiro, e vice-versa:

$ echo abcdef | rev
fedcba

Agora sim, já que nossa linha-problema foi modificada para satisfazer o cut, podemos usá-lo normalmente:

$ echo abcdef | rev | cut -c 1
f
This entry was posted in Shell and tagged , , , , , , . Bookmark the permalink.

3 Responses to Shell: Extrair o último caractere da linha

  1. Já que você usou as expansões do bash, vale a pela utilizá-las também para obter uma substring, no caso, o último caractere:

    $ linha=”abcdef”
    $ pos=${#linha}
    $ echo ${linha:(( pos – 1)):1}
    f

    Ou então tudo numa linha só:
    $ echo ${linha:${#linha}:1}
    f

    Ou deixar mais “cool”, pegando n caracteres finais:
    $ n=3
    $ echo ${linha:(( pos – n)):$n}
    def

    Eu sei q isso funciona no bash e no zsh. Nos outros shells não tenho certeza. E deve até ser mais rápido (sem saco pra fazer os testes com o time :-(), já que não exige a criação de novos processos.

    Belo post!

  2. Ah sim, me esqueci de colocar o “cool” em uma linha só, o mais importante :-)
    $ n=3
    $ echo ${linha:(( ${#linha} – n)):$n}
    def

  3. LES says:

    $ comprimento=$(echo abcdef | wc -L)
    $ echo abcdef | cut -c $comprimento
    6

Leave a Reply

Your email address will not be published. Required fields are marked *