O shell Bourne (/bin/sh) está presente em todas as instalações Unix e scripts escritos nessa linguagem são (bastante) portáveis; man 1 sh
é uma boa referencia.
Básicos
Variáveis e argumentos
Atribui com variável=valor e obtém o conteúdo com $variável
MESSAGE="Hello World" # Atribui uma string PI=3.1415 # Atribui um número decimal N=8 TWON=`expr $N * 2` # Expressão aritmética (somente números inteiros) TWON=$(($N * 2)) # Outra syntax TWOPI=`echo "$PI * 2" | bc -l` # Utiliza o bc para operações de ponto flutuante ZERO=`echo "c($PI/4)-sqrt(2)/2" | bc -l`
Os argumentos de linha de comando
$0, $1, $2, ... # $0 é o comando em si $# # O número de argumentos $* # Todos os argumentos (também $@)
Variáveis especiais
$$ # O ID do processo atual $? # sai do status do ultimo comando command if [ $? != 0 ]; then echo "command failed" fi mypath=`pwd` mypath=${mypath}/file.txt echo ${mypath##*/} # Exibe o filename somente echo ${mypath%%.*} # Caminho completo sem extensão foo=/tmp/my.dir/filename.tar.gz path = ${foo%/*} # Caminho completo sem extensão var2=${var:=string} # Utiliza var se definido, caso contrario utiliza string # atribui string para var e depois para var2. size=$(stat -c%s "$file") # obtém tamanho do arquivo no script bourne filesize=${size:=-1}
Constructs
for file in `ls` do echo $file done count=0 while [ $count -lt 5 ]; do echo $count sleep 1 count=$(($count + 1)) done myfunction() { find . -type f -name "*.$1" -print # $1 é o primeiro argumento da função } myfunction "txt"
Gerar um arquivo
MYHOME=/home/colin cat > testhome.sh << _EOF # Tudo isso vai para dentro do arquivo testhome.sh if [ -d "$MYHOME" ] ; then echo $MYHOME exists else echo $MYHOME does not exist fi _EOF sh testhome.sh
Exemplos de script Bourne
Com um pequeno exemplo, o script utilizado para gerar um livreto PDF a partir desse documento xhtml:
#!/bin/sh # Esse script gera um livre em formato pdf pronto para imprimir em uma impressora duplex if [ $# -ne 1 ]; then # Verifica o argumento echo 1>&2 "Usage: $0 HtmlFile" exit 1 # sai diferente de zero se der erro fi file=$1 # Atribui o filename fname=${file%.*} # Obtém o nome do arquivo somente fext=${file#*.} # Obtém a extensão do arquivo prince $file -o $fname.pdf # Do www.princexml.com pdftops -paper A4 -noshrink $fname.pdf $fname.ps # gera livreto postscript cat $fname.ps |psbook|psnup -Pa4 -2 |pstops -b "2:0,1U(21cm,29.7cm)" > $fname.book.ps ps2pdf13 -sPAPERSIZE=a4 -sAutoRotatePages=None $fname.book.ps $fname.book.pdf # utliza #a4 e #Nenhum no Windows! exit 0 # sair 0 significa sucesso
Alguns comandos awk
Awk é util para field stripping, como cortar de um jeito mais poderoso. Busque esse documento para outros exemplos. Veja por exemplo gnulamp.com e one-liners for awk para mais bons exemplos.
awk '{ print $2, $1 }' file # Imprime e inverte as primeiras duas colunas awk '{printf("%5d : %s\n", NR,$0)}' file # Adiciona números alinhados a esquerda awk '{print FNR "\t" $0}' files # Adiciona números alinhados a direita awk NF test.txt # remove linhas em branco (o mesmo que grep '.') awk 'length > 80' # imprime linha maios que 80 caracteres)
Alguns comandos sed
Aqui está a mina de ourohttp://student.northpark.edu/pemente/sed/sed1line.txt. E uma boa introdução e tutorial ao sedhttp://www.grymoire.com/Unix/Sed.html.
sed 's/string1/string2/g' # Substituí string1 com string2 sed -i 's/wroong/wrong/g' *.txt # Substituí uma palavra recorrente com g sed 's/\(.*\)1/\12/g' # Modifica anystring1 para anystring2 sed '/<p>/,/<\/p>/d' t.xhtml # Exclui linhas que iniciam com <p> # e terminam com </p> sed '/ *#/d; /^ *$/d' # Remove comentários e linha em branco sed 's/[ \t]*$//' # Remove trailing espaces (utilize tab como \t) sed 's/^[ \t]*//;s/[ \t]*$//' # Remove leading e trailing spaces sed 's/[^*]/[&]/' # Cerca primeiro caractere com [] top->[t]op sed = file | sed 'N;s/\n/\t/' > file.num # Numera linhas em um arquivo
Expressões regulares
Algumas expressões regulares básicas úteis para o sed também. Veja Syntax Regex Básicashttp://www.regular-expressions.info/reference.html para uma boa impressão.
[\^$.|?*+() # carácteres especiais, qualquer outros combinarão entre sim \ # ignora caráteres especiais e trata-os como literais * # repete o item anterior zero ou mais vezes . # único carácter exceto caracteres de quebra de linha .* # combina zero ou mais caracteres ^ # combina no inicio de uma linha/string $ # combina o final de uma linha/string .$ # combina um único carácter no dinal da linha/string ^ $ # combina linha com um único espaço [^A-Z] # combina qualquer linha iniciada com qualquer carácter de A to Z
Alguns comandos uteis
O comandos a seguir são úteis para incluir em um script ou como um liners.
sort -t. -k1,1n -k2,2n -k3,3n -k4,4n # Ordena endereço de ip IPv4 echo 'Test' | tr '[:lower:]' '[:upper:]' # Conversão de Case conversion echo foo.bar | cut -d . -f 1 # Retorna foo PID=$(ps | grep script.sh | grep bin | awk '{print $1}') # PID de um script em execução PID=$(ps axww | grep [p]ing | awk '{print $1}') # PID do ping (w/o grep pid) IP=$(ifconfig $INTERFACE | sed '/.*inet addr:/!d;s///;s/ .*//') # Linux IP=$(ifconfig $INTERFACE | sed '/.*inet /!d;s///;s/ .*//') # FreeBSD if [ `diff file1 file2 | wc -l` != 0 ]; then [...] fi # Arquivo alterado? cat /etc/master.passwd | grep -v root | grep -v \*: | awk -F":" \ # Gera http passwd '{ printf("%s:%s\n", $1, $2) }' > /usr/local/etc/apache2/passwd testuser=$(cat /usr/local/etc/apache2/passwd | grep -v \ # Verifica usuário em passwd root | grep -v \*: | awk -F":" '{ printf("%s\n", $1) }' | grep ^user$) :(){ :|:& };: # bash fork bomb. Vai matar a sua máquina tail +2 file > file2 # remove a primeira linha do arquivo
I utilizo esse truque para alterar a extensão do arquivo para muitos arquivos de uma vez. Por exemplo de .cxx para .cpp. Testa-o ante sem o | sh
no final. Você pode tambem fazer isso com o comando rename
se instalado. Ou com o bash builtins.
# ls *.cxx | awk -F. '{print "mv "$0" "$1".cpp"}' | sh # ls *.c | sed "s/.*/cp & &.$(date "+%Y%m%d")/" | sh # ex. copia *.c para *.c.20080401 # rename .cxx .cpp *.cxx # Renomeia todos os .cxx para o cpp # for i in *.cxx; do mv $i ${i%%.cxx}.cpp; done # com o bash builtins