O Julio Neves, uma das referências nacionais sobre shell script, autor de obras sobre o assunto e instrutor frequente em cursos sobre Bash e Zenity, enviou o artigo abaixo sobre algumas das novidades trazidas na versão 4 do Bash, que publico na íntegra com os agradecimentos ao mestre!
Por Julio Neves
Equivale a um
cut
com a opção
-c,
porém muito mais rápido. Preste a atenção, pois neste caso, a origem da contagem é zero.
$ TimeBom=Flamengo
$ echo ${TimeBom:3}
mengo
Essa Expansão de Parâmetros que acabamos de ver, também pode extrair uma sub cadeia, do fim para o principio, desde que seu segundo argumento seja negativo.
$ echo ${TimeBom: -5}
mengo
$ echo ${TimeBom:-5}
Flamengo
$ echo ${TimeBom:(-5)}
mengo
Isto equivale a uma indireção, ou seja devolve o valor apontado por uma variável cujo nome está armazenada em parâmetro.
Exemplo:
$ Ponteiro=VariavelApontada
$ VariavelApontada=”Valor Indireto”
$ echo “A variável \$Ponteiro aponta para \”$Ponteiro\”
> que indiretamente aponta para \”${!Ponteiro}\”"
A variável $Ponteiro aponta para “VariavelApontada”
que indiretamente aponta para “Valor Indireto”
Ambas expandem para os nomes das variáveis prefixadas por parâmetro. Não notei nenhuma diferença no uso das duas sintaxes.
Exemplos:
Vamos listar as variáveis do sistema começadas com a cadeia
GNOME:
$ echo ${!GNOME@}
GNOME_DESKTOP_SESSION_ID GNOME_KEYRING_PID GNOME_KEYRING_SOCKET
$ echo ${!GNOME*}
GNOME_DESKTOP_SESSION_ID GNOME_KEYRING_PID GNOME_KEYRING_SOCKET
Essas expansões foram introduzidas a partir do Bash 4.0 e modificam a caixa das letras do texto que está sendo expandido. Quando usamos circunflexo
(^),
a expansão é feita para maiúsculas e quando usamos vírgula
(,),
a expansão é feita para minúsculas.
Exemplo:
$ Nome=”botelho”
$ echo ${Nome^}
Botelho
$ echo ${Nome^^}
BOTELHO
$ Nome=”botelho carvalho”
$ echo ${Nome^}
Botelho carvalho # Que pena…
Um fragmento de script que pode facilitar a sua vida:
read -p “Deseja continuar (s/n)? “
[[ ${REPLY^} == N ]] && exit
Esta forma evita testarmos se a resposta dada foi um
N
(maiúsculo) ou um
n
(minúsculo).
No Windows, além dos vírus e da instabilidade, também são frequentes nomes de arquivos com espaços em branco e quase todos em maiúsculas. No próximo exemplo veremos como passá-los para minúsculas:
$ cat trocacase.sh
#!/bin/bash
# Se o nome do arquivo tiver pelo menos uma
#+ letra maiúscula, troca-a para minúscula
for Arq in *[A-Z]* # Pelo menos 1 minúscula
do
if [ -f "${Arq,,}" ] # Arq em minúsculas já existe?
then
echo ${Arq,,} já existe
else
mv “$Arq” “${Arq,,}”
fi
done
Elas são usadas para gerar cadeias arbitrárias, produzindo todas as combinações possíveis, levando em consideração os prefixos e sufixos.
Existiam 5 sintaxes distintas, porém o Bash 4.0 incorporou uma 6ª. Elas são escritas da seguinte forma:
onde
lista
são cadeias separadas por vírgulas;
onde os asteriscos
(****)
podem ser substituídos por
lista
ou por um par
inicio..fim;
onde os asteriscos
(****)
podem ser substituídos por
lista
ou por um par
inicio..fim;
onde
incr
é o incremento (ou razão, ou passo). Esta foi introduzida a partir do Bash 4.0.
$ echo {1..A} # Letra e número não funfa
{1..A}
$ echo {0..15..3} # Incremento de 3, só no Bash 4
0 3 6 9 12 15
$ echo {G..A..2} # Incremento de 2 decresc, só no Bash 4
G E C A
$ echo {000..100..10} # Zeros à esquerda, só no Bash 4
000 010 020 030 040 050 060 070 080 090 100
$ eval \>{a..c}.{ok,err}\;
$ ls ?.*
a.err a.ok b.err b.ok c.err c.ok
A sintaxe deste último exemplo pode parecer rebuscada, mas substitua o
eval
por
echo
e verá que aparece:
$ echo \>{a..c}.{ok,err}\;
>a.ok; >a.err; >b.ok; >b.err; >c.ok; >c.err;
Ou seja o comando para o Bash criar os 6 arquivos. A função do
eval
é executar este comando que foi montado.
O mesmo pode ser feito da seguinte maneira:
$ touch {a..z}.{ok,err}
Mas no primeiro caso, usamos Bash puro, o que torna esta forma pelo menos 100 vezes mais rápida que a segunda que usa um comando externo
(touch).