Prompt-doc: "Tira Dúvidas" sobre Shell

Aurelio Marinho Jargas
Curitiba, 04 de Dezembro de 2003



Este é o histórico da linha de comando de uma palestra que fiz para funcionários da Conectiva, sobre Shell Script. O objetivo não era ensinar Shell, mas sim passar dicas e sanar as dúvidas dos participantes, que já conheciam a linguagem e já faziam scripts.


Shell scripts no sistema (exemplos!)

    $ cd /usr/bin
    $ file * | grep -i shell
    $ vi xtrace

Como executar um script (chmod)

    $ cd /tmp
    $ vi teste.sh
    $ ./teste.sh
    $ ls -l teste.sh
    $ chmod +x teste.sh
    $ ls -l teste.sh
    $ ./teste.sh
    $ vi teste.sh
    $ which sh
    $ l /bin/sh
    $ vi teste.sh
    $ ./teste.sh
    $ vi teste.sh

Expansão de variáveis com ${VAR:-} e amigos

    $ a="abcde"
    $ echo $a
    $ echo ${a}
    $ echo ${#a}
    $ echo ${a:-FOO}
    $ unset a
    $ echo $a
    $ echo ${a:-FOO}
    $ if [ -z "$a" ]; then a=FOO ; fi
    $ unset a
    $ echo $a
    $ echo ${a:-FOO}
    $ echo ${a:=FOO}
    $ echo $a
    $ echo ${a:+FOOoooooooo}

Expansão avançada do bash2 (tipo sed)

    $ echo $a
    $ echo ${a/O/.}      # sed s///
    $ echo ${a//O/.}     # sed s///g
    $ echo $a | sed 's/O/./g'
    $ echo ${a//O/.tyturtu}
    $ rpm -q bash
    $ b=O
    $ echo ${a//$b/.}

Eval

    $ a="ls"
    $ echo $a
    $ eval $a
    $ ${!a}
    $ : ${!a}
    $ echo ${!a}

Diferença do echo com aspas (mantém espaços) e sem

    $ echo ahyi dfy dfui yidfs dfis ui       fd yifsdy idfsy isdf
    $ echo "ahyi dfy dfui yidfs dfis ui       fd yifsdy idfsy isdf"
    $ a="ahyi dfy dfui yidfs dfis ui       fd yifsdy idfsy isdf"
    $ echo $a
    $ echo "$a"
    $ cat /etc/fstab
    $ cat /etc/fstab | grep swap
    $ cat /etc/fstab | grep swap | sed -n l
    $ var=$(cat /etc/fstab | grep swap)
    $ echo $var
    $ echo "$var"

Subshell com crase ou $(), prefira o $()

    $ var=`date`
    $ echo $var
    $ var=$(date)
    $ echo $var
    $ var=$(echo `cat /etc`)

As aspas simples protegem, não expandem vars nem comandos

    $ a="abc"
    $ echo $a
    $ echo "$a"
    $ echo '$a'
    $ echo '$a $(date)'
    $ echo "$a $(date)"

Ao definir uma variável não pode ter espaços!

    $ a = ''

O pesadelo dos escapes...

    $ a='\'
    $ echo $a
    $ a="\"
    $ echo $a
    $ echo \$a
    $ a="\"
    $ "
    $ a=' \'    '
    $ a="\\"
    $ echo $a

O sed e os escapes (use o echo para ajudar!)

    $ echo "//bla//"   # mudar para \\bla\\
    $ echo "//bla//" | sed "s///\/"
    $ echo "//bla//" | sed "s/\//\\/"
    $ echo "s/\//\\/"
    $ echo 's/\//\\/'
    $ echo "//bla//" | sed 's/\//\\/'
    $ echo "//bla//" | sed 's/\//\\/g'
    $ a='/'
    $ echo "//bla//" | sed "s/$a/\\/g"
    $ echo "s/$a/\\/g"
    $ a="\\/"
    $ echo $a
    $ echo "//bla//" | sed "s/$a/\\/g"
    $ echo "s/$a/\\/g"
    $ echo "//bla//" | sed "s/$a/\\\/g"
    $ $(echo "//bla//" | sed "s/$a/\\\/g")
    $ echo $(echo "//bla//" | sed "s/$a/\\\/g")

O sed pode usar qualquer delimitador fora o s///

    $ echo isso | sed s/isso/aquilo/g
    $ echo isso | sed s,isso,aquilo,g
    $ echo isso | sed s isso aquilo g
    $ echo isso | sed 's isso aquilo g'
    $ echo isso | sed 's9isso9aquilo9g'
    $ echo isso | sed 's
    $ isso
    $ aquilo
    $ g'
    $ echo isso | sed 's|isso|aquilo|g'
    $ echo isso | sed 'sáissoáaquiloág'
    $ echo isso | sed 's§isso§aquilo§g'
    $ echo isso | sed 's"isso"aquilo"'
    $ echo isso | sed 's	isso	aquilo'
    $ echo isso | sed 's	isso	aquilo	'

Como "ver" se é um TAB ou espaços

    $ echo -e "\ta\ta"
    $ echo -e "\ta\ta" | sed -n l
    $ echo -e "\ta\ta" | od -c
    $ echo -ne "\ta\ta" | od -c
    $ echo -n "bla"
    $ echo -ne "bla\n"
    $ echo "bla"

Como depurar (debug) scripts: sh -x, set -x, ...

    $ sh -x teste.sh
    $ sh teste.sh
    $ vi teste.sh
    $ ./teste.sh
    $ set -x
    $ ./teste.sh
    $ echo
    $ vi teste.sh
    $ ./teste.sh
    $ vi teste.sh
    $ set +x
    $ vi teste.sh

Como pegar a saída de erro (STDERR, 2)

    $ cp
    $ cp | grep arqu
    $ ls > foo
    $ cat foo
    $ cp > foo
    $ cat foo
    $ cp 1> foo
    $ cp 1> foo 2> foo
    $ cat foo
    $ cp 2> foo
    $ ./teste.sh
    $ ./teste.sh 2> foo
    $ ./teste.sh > foo
    $ ./teste.sh > foo 2> foo
    $ cat foo
    $ ./teste.sh > foo 2>&1
    $ cat foo
    $ ./teste.sh > foo 2>&1
    $ ./teste.sh 2>&1
    $ cp
    $ cp 2>&1
    $ cp 2>&1 | grep arqui

O comando test, seu sósia [ e o código de retorno $?

    $ if [ $var = 'abc' ] ; then echo OK ; fi
    $ which [
    $ l /usr/bin/[
    $ if test $var = 'abc' ; then echo OK ; fi
    $ if grep -qs root /etc/passwd ; then echo tem ; fi
    $ grep -qs root /etc/passwd
    $ echo $?
    $ grep -qs roiiiiiiot /etc/passwd
    $ echo $?
    $ cp
    $ echo $?
    $ exit abnc
    $ cp 2>/dev/null
    $ echo $?
    $ ls /dev/null

O [[ para fazer testes

    $ if [ 1 -gt 5 ]; then echo é menor ; fi
    $ if [ 8 -gt 5 ]; then echo é maior ; fi
    $ if [[ 8 -gt 5 ]]; then echo é maior ; fi
    $ if [[ 8  5 ]]; then echo é maior ; fi

Os operadores lógicos AND && e OR ||

    $ cp 2>/dev/null ; echo $?
    $ cp 2>/dev/null && echo OK
    $ ls 2>/dev/null && echo OK
    $ ls >/dev/null 2>&1 && echo OK
    $ ls >/dev/null 2>&1 || echo OK
    $ cp 2>/dev/null || echo OK
    $ cp 2>/dev/null || echo OK && echo NOK
    $ echo && echo OK || echo NOK
    $ echo && cp 2>/dev/null || echo NOK
    $ false && cp 2>/dev/null || echo NOK
    $ false && cp || echo NOK
    $ true && cp || echo NOK
    $ false && cp || echo NOK
    $ false && cp || echo NOK && echo OKDENOVO
    $ false && { cp || echo NOK && echo OKDENOVO ; }
    $ true && { cp || echo NOK && echo OKDENOVO ; }

Checagem de parâmetros da linha de comando ($1)

    $ test -z "$1" || { echo uso: blabla ; exit 1  ; }
    $ [ "$1" ] || { echo uso: blabla ; exit 1  ; }
    $ [ "$1" ] || { echo uso: blabla ; echo exit 1  ; }
    $ [ $1 ] || { echo uso: blabla ; echo exit 1  ; }
    $ [ $1 = '--help' ] || { echo uso: blabla ; echo exit 1  ; }
    $ [ "$1" = '--help' ] || { echo uso: blabla ; echo exit 1  ; }
    $ [  = '--help' ] || { echo uso: blabla ; echo exit 1  ; }

Como passar parâmetros vazios

    $ vi teste.sh
    $ ./teste.sh
    $ ./teste.sh ""
    $ ./teste.sh "" dois
    $ ./teste.sh "" "" dois

As ferramentas: cut

    $ cat /etc/passwd | cut -d: -f5
    $ cat /etc/passwd | cut -d: -f5,2
    $ cat /etc/passwd | cut -d: -f5,2,1
    $ cat /etc/passwd | cut -d: -f5-
    $ cat /etc/passwd | cut -d: -f5-6
    $ cat /etc/passwd | cut -d: -f5-7
    $ cat /etc/passwd | cut -c 1-10
    $ cat /etc/passwd | cut -c 10-

As ferramentas: awk

    $ cat /etc/passwd | awk '{print $3}'
    $ cat /etc/passwd | awk '{print $3}'
    $ cat /etc/passwd | awk '{print $2}'
    $ cat /etc/passwd | awk '{print $1}'
    $ cat /etc/passwd | awk '{print $2}'
    $ cat /etc/passwd | awk -F: '{print $2}'
    $ cat /etc/fstab
    $ cat /etc/fstab | cut -d" " -f4
    $ cat /etc/fstab | awk '{print $4}'

As ferramentas: tr

    $ a="asd asd       k		ioioio"
    $ echo $a
    $ echo "$a"
    $ echo "$a" | tr -s ' '
    $ echo aaaaabbbb | tr -s a
    $ echo aaaaabbbb | tr -s ab
    $ echo aaaaabbbb | tr a-z A-Z
    $ echo aaaaabbbb | tr abcdef ABCDEF
    $ echo aaaaabbbb | tr abcdef XVDGFFG

As ferramentas: sort

    $ cat /etc/passwd
    $ cat /etc/passwd | sort
    $ cat /etc/passwd | sort -r

As ferramentas: rev, tac

    $ cat /etc/passwd | rev
    $ echo abcde | rev
    $ echo cat | rev
    $ tac /etc/passwd
    $ tac /etc/passwd| rev

As ferramentas: sort, uniq

    $ vi txt
    $ cat txt | sort
    $ cat txt | sort | uniq
    $ cat txt | uniq
    $ cat txt | sort -u
    $ cat txt | sort | uniq

As ferramentas: wc

    $ cat /etc/passwd | wc
    $ cat /etc/passwd | wc -w
    $ cat /etc/passwd | wc -l
    $ cat /etc/passwd | wc -c

As ferramentas: cat, paste

    $ vi txt2
    $ cat txt txt2
    $ paste txt txt2
    $ paste -s txt txt2

As ferramentas: tee

    $ echo abc
    $ echo abc | sed 's/a/./'
    $ echo abc | tee a | sed 's/a/./'
    $ cat a

As ferramentas: head, tail

    $ head /etc/passwd
    $ head -2 /etc/passwd
    $ tail -2 /etc/passwd
    $ tail  /etc/passwd

As ferramentas: seq

    $ for i in 1 2 3 4 5 5 6 7 8 9 10; do echo $i-- ; done
    $ for i in 1 2 3 4 5 5 6 abd hjerer jrtj 8 9 10; do echo $i-- ; done
    $ for i in $(seq 10); do echo $i-- ; done
    $ seq 10
    $ seq 2
    $ seq 2 5
    $ seq 5 2
    $ seq 4 8 50

As ferramentas: printf

    $ printf "%s" bla
    $ printf "%s\n" bla
    $ printf "%10s\n" bla
    $ printf "%-10s\n" bla
    $ printf "%10s----\n" bla
    $ printf "%-10s----\n" bla
    $ printf "%10s----\n" blaasdasdasdasd
    $ printf "%d" 5
    $ printf "%d\n" 5
    $ printf "%4d\n" 5
    $ printf "%4d\n" 5 | sed 's/ /0/g'
    $ printf "%.4d\n" 5
    $ printf "%4.2f\n" 5

As ferramentas: grep

    $ cat /etc/passwd
    $ cat /etc/passwd | grep root
    $ cat /etc/passwd | grep -i root
    $ cat /etc/passwd | grep -i ROOT
    $ cp
    $ echo $LANG
    $ cat /etc/passwd | grep -w root
    $ cat /etc/passwd | grep -w roo
    $ cat /etc/passwd | grep -x roo
    $ cat /etc/passwd | grep -l roo
    $ grep -l roo /etc/passwd
    $ grep -v roo /etc/passwd
    $ grep -v root /etc/passwd
    $ VAR=root
    $ grep -i $VAR /etc/passwd
    $ grep g /etc/passwd
    $ grep g\$ /etc/passwd
    $ fgrep g\$ /etc/passwd
    $ fgrep g /etc/passwd
    $ cd /bin
    $ l grep egrep fgrep

As ferramentas: find

    $ find . -type f
    $ find . -type d
    $ find . -type l
    $ ln -s a z
    $ find . -type l
    $ find . -type f
    $ find . -type f -exec echo rm -f {} \;
    $ find . -type f -ok echo rm -f {} \;
    $ find . -type f | while read BOZO; do echo $BOZO; done
    $ cat /etc/passwd | while read BOZO; do echo $BOZO; done
    $ cat /etc/passwd | while read BOZO; do echo {{$BOZO}}; done
    $ cat /etc/passwd | while read BOZO; do echo $BOZO | grep -qs root && echo $BOZO; done
    $ find . -type f -exec echo rm -f {}\;

As ferramentas: date

    $ date
    $ date +'%y %m %d'
    $ date +'%Y %m %d'
    $ date --help
    $ date +'%Y-%m-%d'
    $ date +'%Y-%m-%d %H:%M'
    $ date +'hoje é %Y-%m-%d %H:%M ... '
    $ date +'%s'
    $ date +'%s'
    $ date +'%s'

As ferramentas: diff, vi -d

    $ cat txt txt2
    $ diff txt txt2
    $ vi txt2
    $ cp txt txt3
    $ vi txt3
    $ diff txt txt3
    $ diff -u txt txt3
    $ diff -u txt txt3 | vi -
    $ vi txt3
    $ diff -u txt txt3 | vi -
    $ vi txt3
    $ diff -u txt txt3 | vi -
    $ vi txt3
    $ diff -u txt txt3 | vi -
    $ vi -d txt txt3

Funções separadas em uma biblioteca

    $ cds
    $ vi functions
    $ ./functions
    $ source functions
    $ . functions
    $ vi inet

Voltar para a página dos cursos na Conectiva