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
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!
Ah sim, me esqueci de colocar o “cool” em uma linha só, o mais importante :-)
$ n=3
$ echo ${linha:(( ${#linha} – n)):$n}
def
$ comprimento=$(echo abcdef | wc -L)
$ echo abcdef | cut -c $comprimento
6