Se você está começando com scripts Bash no Linux, obter um conhecimento sólido do básico será de grande ajuda. Eles são a base de um conhecimento mais profundo e de habilidades de script mais avançadas.
Índice
Lembre-se, torne seus scripts executáveis
Para que o shell execute um script, o script deve ter a permissão do arquivo executável definida. Sem isso, seu script é apenas um arquivo de texto. Com ele, ainda é um arquivo de texto, mas o shell sabe que contém instruções e tentará executá-las quando o script for iniciado.
O objetivo de escrever scripts é que eles sejam executados, então o primeiro passo básico é saber como informar ao Linux que seu script deve ser considerado executável.
O
chmod
comando nos permite definir permissões de arquivo. A permissão de execução pode ser definida com o sinalizador +x.
chmod +x script1.sh
Você precisará fazer isso com cada um dos seus scripts. Substitua “script1.sh” pelo nome do seu script.
1. Qual é essa estranha primeira linha?
A primeira linha de um script informa ao shell qual interpretador deve ser chamado para executar esse script. A primeira linha deve começar com um shebang, “#!”, também conhecido como hashbang. O “#!” informa ao shell que esta linha contém o caminho e o nome do interpretador para o qual o script foi escrito.
Isso é importante porque se você escreveu um script para ser executado no Bash, não deseja que ele seja interpretado por um shell diferente. É provável que haja incompatibilidades. Bash — como a maioria dos shells — tem suas próprias peculiaridades de sintaxe e funcionalidade que outros shells não terão ou terão implementado de forma diferente.
Quando você executa um script, o shell atual abre o script e determina qual shell ou interpretador deve ser usado para executar esse script. Em seguida, ele inicia esse shell e passa o script para ele.
#!/bin/bashecho Executando em $SHELL
A primeira linha deste script pode ser lida como “Use o interpretador localizado em /bin/bash para executar este script.”
A única linha do script grava o valor contido na $SHELL
variável ambiental na tela do terminal. Isso confirma que o Bash foi usado para executar o script.
./script1.sh
Como um truque de salão, podemos demonstrar que o script é passado para qualquer intérprete que selecionarmos.
#!/bin/gatoTodas as linhas de texto são passadas para o comando cat
e são impressos na janela do terminal. Isso inclui
a linha shebang.
script2.sh
Este script é iniciado pelo shell atual e passado para o cat
comando . O cat
comando “executa” o script.
Escrever suas coisas assim pressupõe que você sabe onde o shell ou outro intérprete está localizado na máquina de destino. E 99% das vezes, tudo bem. Mas algumas pessoas gostam de proteger suas apostas e escrever suas coisas assim:
#!/usr/bin/env bashecho Executando em $SHELL
script3.sh
Quando o script é iniciado, o shell procura a localização do shell nomeado. Se o shell estiver em um local fora do padrão, esse tipo de abordagem pode evitar erros de “mau intérprete”.
Não escute, ele está mentindo!
No Linux, sempre há mais de uma maneira de esfolar um gato ou provar que o autor está errado. Para ser totalmente factual, existe uma maneira de executar scripts sem complicações e sem torná-los executáveis.
Se você iniciar o shell que deseja executar o script e passar o script como um parâmetro de linha de comando , o shell irá iniciar e executar o script — seja ele executável ou não. Como você escolhe o shell na linha de comando, não há necessidade de nada.
Este é o script completo:
echo "Fui executado por" $SHELL
Usaremos ls
para ver se o script realmente não é executável e iniciaremos o Bash com o nome do script:
eu
bash script4.sh
Também existe uma maneira de executar um script pelo shell atual, e não por um shell iniciado especificamente para executar o script. Se você usar o source
comando, que pode ser abreviado para um único ponto ” .
“, seu script será executado pelo seu shell atual.
Portanto, para executar um script sem shebang, sem a permissão do arquivo executável e sem iniciar outro shell, você pode usar qualquer um destes comandos :
fonte script4.sh
. script4.sh
Embora isso seja possível, não é recomendado como solução geral. Existem desvantagens.
Se um script não contém um shebang, você não poderá dizer para qual shell ele foi escrito. Você vai se lembrar daqui a um ano? E sem a permissão executável definida no script, o ls
comando não o identificará como um arquivo executável, nem usará cores para distinguir o script dos arquivos de texto simples.
2. Impressão de texto
Escrever texto no terminal é um requisito comum. Um pouco de feedback visual ajuda muito.
Para mensagens simples, o echo
comando será suficiente . Ele permite alguma formatação do texto e também permite trabalhar com variáveis.
#!/bin/bashecho Esta é uma string simples.
echo "Esta é uma string contendo 'aspas simples', portanto está entre aspas duplas."
echo "Isto imprime o nome do usuário:" $USER
echo -e "A opção -e nos permite usar\ndiretivas de formatação\para dividir a string."
./script5.sh
O printf
comando nos dá mais flexibilidade e melhores recursos de formatação, incluindo conversão de números.
Este script imprime o mesmo número usando três bases numéricas diferentes. A versão hexadecimal também é formatada para imprimir em letras maiúsculas, com zeros à esquerda e largura de três dígitos.
#!/bin/bashprintf "Decimal: %d, Octal: %o, Hexadecimal: %03X\n" 32 32 32
./script6.sh
Observe que, diferentemente de echo
, você deve informar printf
para iniciar uma nova linha com o \n
token ” “.
3. Criação e uso de variáveis
As variáveis permitem armazenar valores dentro do seu programa e manipulá-los e usá-los. Você pode criar suas próprias variáveis ou usar variáveis de ambiente para valores do sistema.
#!/bin/bashmillennium_text="Anos desde o milênio:"
hora_atual=$(data '+%H:%M:%S' )
data_hoje=$(data '+%F' )
ano=$(data '+%Y' )
echo "Hora atual:" $hora_atual
echo "Data de hoje:" $hoje_data
anos_desde_Y2K=$(( ano - 2000 ))
eco $ millennium_text $ anos_desde_Y2K
Este script cria uma variável de string chamada millennium_text
. Ele contém uma linha de texto.
Em seguida, ele cria três variáveis numéricas.
- A
current_time
variável é inicializada no momento em que o script é executado. - A
todays_date
variável é definida como a data em que o script é executado. - A
year
variável contém o ano atual.
Para acessar o valor armazenado em uma variável, preceda seu nome com um cifrão “$”.
./script7.sh
O script imprime a hora e a data, calcula quantos anos se passaram desde o milênio e armazena isso na years_since_Y2K
variável.
Por fim, imprime a string contida na millennium_text
variável e o valor numérico armazenado no arquivo years_since_Y2K
.
4. Tratamento da entrada do usuário
Para permitir que um usuário insira um valor que o script usará, você precisa ser capaz de capturar a entrada do teclado do usuário. O comando Bash read
permite fazer exatamente isso. Aqui está um exemplo simples.
#!/bin/bashecho "Digite um número e pressione \"Enter\""
leia número_usuário1;
echo "Digite outro número e pressione \"Enter\""
leia user_number2;
printf "Você digitou: %de %d\n" $user_number1 $user_number2
printf "Somados eles formam: %d\n" $(( user_number1 + user_number2))
O script solicita dois números. Eles são lidos no teclado e armazenados em duas variáveis, user_number1
e user_number2
.
O script imprime os números na janela do terminal, soma-os e imprime o total.
./script8.sh
Podemos combinar os prompts nos read
comandos usando a -p
opção (prompt).
#!/bin/bashread -p "Digite um número e pressione \"Enter\" " user_number1;
read -p "Digite outro número e pressione \"Enter\" " user_number2;
printf "Você digitou: %de %d\n" $user_number1 $user_number2
printf "Somados eles formam: %d\n" $(( user_number1 + user_number2))
Isso torna as coisas mais organizadas e fáceis de ler. Scripts fáceis de ler também são mais fáceis de depurar.
./script9.sh
O script se comporta de maneira um pouco diferente agora. A entrada do usuário está na mesma linha do prompt.
Para capturar a entrada do teclado sem que ela seja ecoada na janela do terminal, use a -s
opção (silencioso).
#!/bin/bashleia -s -p "Digite seu PIN secreto e pressione \"Enter\" " secret_PIN;
printf "\nShhh ... é %d\n" $secret_PIN
./script10.sh
O valor de entrada é capturado e armazenado em uma variável chamada secret_PIN
, mas não é exibido na tela quando o usuário o digita. O que você fará depois disso depende de você.
5. Aceitando Parâmetros
Às vezes é mais conveniente aceitar a entrada do usuário como parâmetros de linha de comando do que deixar um script esperando pela entrada. Passar valores para um script é fácil. Eles podem ser referenciados dentro do script como se fossem qualquer outra variável.
O primeiro parâmetro torna-se variável $1
, o segundo parâmetro torna-se variável $2
e assim por diante. A variável $0
sempre contém o nome do script e a variável $#
contém o número de parâmetros que foram fornecidos na linha de comando. Variável $@
é uma string que contém todos os parâmetros da linha de comando.
#!/bin/bashprintf "Este script se chama: %s\n" $0
printf "Você usou %d parâmetros de linha de comando\n" $#
#percorre as variáveis
para parâmetro em "$@"; fazer
echo "$param"
feito
echo "O parâmetro 2 era:" $2
Este script usa $0
e $#
para imprimir algumas informações. em seguida, usa ?@
para percorrer todos os parâmetros da linha de comando. Ele é usado $2
para mostrar como acessar um único valor de parâmetro específico.
./script11.sh
Colocar várias palavras entre aspas “”” combina-as em um único parâmetro.
6. Lendo dados de arquivos
Saber como ler dados de um arquivo é uma ótima habilidade. Podemos fazer isso no Bash com um loop while .
#!/bin/bashContagem de linhas = 0
enquanto IFS='' leia -r LinefromFile || [[ -n "${LinefromFile}" ]]; fazer
((ContagemLinha++))
echo "Lendo linha $LineCount: ${LinefromFile}"
concluído < "$1"
Estamos passando o nome do arquivo que queremos que o script processe como um parâmetro de linha de comando. Será o único parâmetro, portanto dentro do script $1
conterá o nome do arquivo. Estamos redirecionando esse arquivo para o while
loop.
O while
loop define o separador de campo interno como uma string vazia, usando a IFS=''
atribuição. Isso evita que o read
comando divida linhas em espaços em branco. Somente o retorno de carro no final de uma linha é considerado o verdadeiro final da linha.
A [[ -n "${LinefromFile}" ]]
cláusula prevê a possibilidade de que a última linha do arquivo não termine com um retorno de carro. Mesmo que isso não aconteça, a última linha será tratada corretamente e tratada como uma linha regular compatível com POSIX.
./script12.sh twinkle.txt
7. Usando testes condicionais
Se quiser que seu script execute ações diferentes para condições diferentes, você precisará realizar testes condicionais. A sintaxe de teste de colchetes duplos oferece um número esmagador de opções.
#!/bin/bashpreço=$1
se [[ preço -ge 15 ]];
então
echo "Muito caro."
outro
echo "Compre!"
fi
Bash fornece um conjunto completo de operadores de comparação que permitem determinar coisas como se um arquivo existe , se você pode lê-lo, se pode escrever nele e se existe um diretório.
Ele também possui testes numéricos para igual -qe
, maior que -gt
, menor que ou igual -le
e assim por diante, embora você também possa usar a notação familiar ==
,, .>=
<=
./script13.sh 13
./script13.sh 14
./script13.sh 15
./script13.sh 16
8. O poder dos loops for
Repetir ações continuamente é melhor realizado usando loops. Um for
loop permite que você execute um loop várias vezes . Isso pode ser até um número específico ou até que o loop percorra uma lista de itens.
#!/bin/bashpara (( i=0; i<=$1; i++ ))
fazer
echo "Loop for estilo C:" $i
feito
para eu em {1..4}
fazer
echo "Loop For com intervalo:" $i
feito
para eu em "zero" "um" "dois" "três"
fazer
echo "For loop com uma lista de palavras:" $i
feito
site = "Como ser geek"
para eu em $website
fazer
echo "For loop com uma coleção de palavras:" $i
feito
Todos esses loops são for
loops, mas funcionam com diferentes tipos de instruções e dados de loop.
./script14.sh3
for
O primeiro loop é um loop clássico de estilo C. O contador do loop i
é inicializado em zero e incrementado a cada ciclo do loop. Embora o valor de i
seja menor ou igual ao valor mantido em $1
, o loop continuará em execução.
O segundo loop funciona através de um intervalo de números de 1 a 4. O terceiro loop funciona através de uma lista de palavras. Embora haja mais palavras para processar, o loop continua se repetindo.
O último loop funciona através da lista de palavras em uma variável string.
9. Funções
As funções permitem encapsular seções de código em rotinas nomeadas que podem ser chamadas de qualquer lugar dentro do seu script.
Suponha que quiséssemos que nosso script que lê linhas de um arquivo fizesse algum tipo de processamento em cada linha. Seria conveniente ter esse código contido em uma função.
#!/bin/bashContagem de linhas = 0
função contagem_palavras() {
printf "%d palavras na linha %d\n" $(echo $1 | wc -w) $2
}
enquanto IFS='' leia -r LinefromFile || [[ -n "${LinefromFile}" ]]; fazer
((ContagemLinha++))
count_words "$LinefromFile" $LineCount
concluído < "$1"
count_words "Isso não está no loop" 99
Modificamos nosso programa de leitura de arquivos adicionando uma função chamada count_words
. Ele é definido antes de precisarmos usá-lo.
A definição da função começa com a palavra function
. Isto é seguido por um nome exclusivo para nossa função seguido por parênteses ” ()
.” O corpo da função está contido entre chaves “{}”.
A definição da função não faz com que nenhum código seja executado. Nada na função é executado até que a função seja chamada.
A count_words
função imprime o número de palavras em uma linha de texto e o número da linha. Esses dois parâmetros são passados para a função da mesma forma que os parâmetros são passados para um script. O primeiro parâmetro torna-se variável de função $1
e o segundo parâmetro torna-se variável de função $2
e assim por diante.
O while
loop lê cada linha do arquivo e passa para a count_words
função, junto com o número da linha. E só para mostrar que podemos chamar a função de diferentes locais do script, chamamos-na mais uma vez fora do while
loop.
./script15.sh twinkle.txt
Não tema a curva de aprendizado
Os scripts são gratificantes e úteis, mas difíceis de entender. Depois de adquirir algumas técnicas reutilizáveis, você será capaz de escrever scripts que valem a pena com relativa facilidade. Então você pode examinar funcionalidades mais avançadas.
Caminhe antes de correr e reserve um tempo para aproveitar a viagem.