Este é o histórico da linha de comando de uma palestra que fiz na Sucesu-PR para uma turma de 20 alunos, sobre SED e Expressões Regulares.
O SED é o Stream EDitor, um editor de textos não interativo, automático, um filtro.
$ seq 12 > numeros.txt
$ vi numeros.txt
$ cat numeros.txt
1:um:one
2:dois:two
3:tres:three
4:quatro:four
5:cinco:five
6:seis:six
7:sete:seven
8:oito:eight
9:nove:nine
10:dez:ten
11:onze:eleven
12:doze:twelve
$ ed
$ ed numeros.txt
$ echo aula
$ echo aula | sed s/a/A/
$ cat numeros.txt
$ sed s/e/E/ numeros.txt
$ sed s/e/E/g numeros.txt # modificador 'g' de Global (troca todas)
$ cat numeros.txt | sed 5d
$ cat numeros.txt | sed 1d
$ cat numeros.txt | sed 10d
$ cat numeros.txt | sed $d # ERRO! variável $d
$ cat numeros.txt | sed '$d' # _sempre_ usar aspas no shell
$ cat numeros.txt | sed 'y/aeiou/AEIOUL/'
$ cat numeros.txt | sed 'y/aeiou/AEIOU/'
$ cat numeros.txt | tr a-z A-Z
$ cat numeros.txt | sed 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'
$ cat numeros.txt | sed 'y/abcdefghi/iejsyfnch/' # mini encriptador
$ cat numeros.txt | sed 'y/abcdefghi/iejsyfnch/' | sed 'y/iejsyfnch/abcdefghi/'
$ cat numeros.txt | tr abcdefghi iejsyfnch
$ cat numeros.txt | sed 5p # duplica
$ cat numeros.txt | sed -n 5p # só mostra a 5a linha
$ cat numeros.txt | sed -n s/nove/nnn/
$ cat numeros.txt | sed -n s/nove/nnn/p
$ cat numeros.txt | sed -n p
$ cat numeros.txt | sed -n 5p
$ cat numeros.txt | sed s/nove/nnn/
$ cat numeros.txt | sed 5s/nove/nnn/
$ cat numeros.txt | sed '5 s/nove/nnn/' # endereço junto ou separado
$ cat numeros.txt | sed '5 s/nove/nnn/' # vários espaços e/ou TAB
$ cat numeros.txt | sed '999s/nove/nnn/'
$ cat numeros.txt | sed '5d'
$ cat numeros.txt | sed '5,8 d' # um intervalo de 4 linhas
$ cat numeros.txt | sed '5d 7d 9d' # errado
$ cat numeros.txt | sed '5d ; 7d ; 9d' # certo
$ cat numeros.txt | sed -n 's/nove/nnn/p'
$ cat numeros.txt | sed -n 's/nove/nnn/p ; s/nove/NNN/p'
$ cat numeros.txt | sed -n 's/XXXX/nnn/p ; s/nove/NNN/p'
$ cat numeros.txt | sed -n 's/nove/nnn/p ; s/nnn/NNN/p'
$ cat numeros.txt | sed -n 's/nove/nnn/ ; s/nnn/NNN/p'
$ cat numeros.txt | sed -n 's/nove/nnn/ ; s/nnn/NNN/; 9p'
$ cat numeros.txt | sed -n 's/nove/nnn/ ; 9p; s/nnn/NNN/; 9p'
$ cat numeros.txt | sed -n '9p; s/nove/nnn/ ; 9p; s/nnn/NNN/; 9p'
$ cat numeros.txt | sed '5,$ d' # da 5a linha ao final
$ cat numeros.txt | sed -n '1,4 p' # idem anterior
$ cat numeros.txt | sed -n '5p;5p;5p;5p'
$ cat numeros.txt | sed '9d ; 7d ; 5d'
$ cat numeros.txt | sed -n '9p ; 7p ; 5p'
$ cat numeros.txt | sed -n '/quatro/ p'
$ cat numeros.txt | sed -n '/o/ p' # emulando o grep!
$ cat numeros.txt | grep o
$ l -l /bin/sed /bin/grep # quem é menor?
$ l -l /bin/sed /bin/gawk # e agora? :)
$ cat numeros.txt | sed -n '/o/ p'
$ cat numeros.txt | sed -n '/quatro/ p'
$ cat numeros.txt | sed -n '/quatro/ d'
$ cat numeros.txt | sed '/quatro/ d'
$ cat numeros.txt | sed '/:/ d'
$ cat numeros.txt | sed '/o/ d' # apaga as linhas 'o'
$ cat numeros.txt | sed '/o/! d' # não apaga as linhas 'o'
$ cat numeros.txt | sed '/dois/,/cinco/ d'
$ cat numeros.txt | sed '/dois/,6 d'
$ cat numeros.txt | sed '8,6 d'
$ cat numeros.txt | sed 'd' # sem endereço == todas
$ cat numeros.txt | sed '1,/dois/ d'
$ cat numeros.txt | sed '/dois/,$ d'
$ cat numeros.txt | sed '/4/,$ d' # o $ é a última linha
$ cat numeros.txt | sed '4~2 d' # não funciona no UNIX!
$ cat numeros.txt | sed '1~2 d' # linhas ímpares
$ cat numeros.txt | sed '2~2 d' # linhas pares
$ cat numeros.txt | sed '1~5 d' # pule de 5 em 5
$ sed -V # dependendo da versão
$ echo aaa | sed 's/a/a\n/g' # aceita \n, \t, ...
$ echo aaa | sed 's/a/a\t/g'
$ echo aaa | sed 's/a/a /g' # quando não, Ctrl+V TAB
$ cat /etc/passwd
$ cat /etc/passwd | sed -n '/edival/ p'
$ cat /etc/passwd | sed -n '/edival/ p' | sed 's/:/\n/g'
$ cat numeros.txt | sed q
$ cat numeros.txt | head -n 4 # as 4 primeiras
$ cat numeros.txt | sed 4q # idem anterior
$ cat numeros.txt | sed 's/e/___/g'
$ cat numeros.txt | sed '4,6 s/e/___/g'
$ cat numeros.txt | sed '/dois/,/cinco/ s/e/___/g'
$ cat numeros.txt | sed '/dois/,/cinco/s/e/___/g'
$ echo a/a/a | sed 's/a/A/g'
$ echo a/a/a | sed 's///@/g' # erro
$ echo a/a/a | sed 's/\//@/g' # ok
$ echo a/a/a | sed 's^/^@^g' # ^
$ echo a/a/a | sed 's4/4@4g' # 4
$ echo a/a/a | sed 's / @ g' # espaço
$ echo a/a/a | sed 'ss/s@sg' # s
$ echo a/a/a | sed 's / @ g' # TAB
$ echo a/a/a | sed 's§/§@§g' # §
$ echo a/a/a | sed 's¢/¢@¢g' # ¢
$ echo a/a/a | sed 's
> /
> @
> g # Enter
$ echo a/a/a | sed '/\// s^/^@^g'
$ echo a/a/a | sed '\@/@ s^/^@^g' # \@end@
$ echo a/a/a | sed '\ / s / @ g' # espaço
$ cat numeros.txt | sed '5s/:/_/g ; 5s/i/X/g'
$ cat numeros.txt | sed '5 { s/:/_/g ; s/i/X/g ; }'
$ echo aaaaa | sed 's/a/X/' # nenhum
$ echo aaaaa | sed 's/a/X/g' # g - global
$ echo aaaaa | sed -n 's/a/X/gp' # p - print
$ echo aaaaa | sed 's/a/X/3' # número
$ echo aaaaa | sed 's/a/X/9'
$ echo aaaaa | sed 's/a/X/w foo' # w - write
$ cat foo
$ echo -e "\aXX\tXX"
$ echo -e "\aXX\tXX" | sed -n l # mostra invisíveis
$ echo -e "\aXX\tXX " | sed -n l # $ indica fim da linha
$ echo -e "\aXX\tXX " | od -c # comando similar
$ cat numeros.txt | sed 'n' # faz nada
$ cat numeros.txt | sed 'n;d' # apaga linhas pares
$ cat numeros.txt | sed '1d;n;d' # apaga linhas ímpares
$ cat numeros.txt | grep -A1 oito
$ cat numeros.txt | sed -n '/oito/{p;n;p;}' # similar do grep -A1
$ cat numeros.txt | sed -n '/um/{N;l;}' # junta e separa com \n
$ cat numeros.txt | sed -n '/um/{N; s/\n/@/p ;}'
$ cat numeros.txt | sed -n '/um/{N;N;N;s/\n/@/gp ;}'
$ cat numeros.txt | sed -n 'N;N;s/\n/@@@/gp' # junta de 3 em 3
$ cat numeros.txt | sed ':a' # marca a posição 'a'
$ cat numeros.txt | sed : # comando nulo == cat
$ cat numeros.txt | sed ':a ; N ; b a' # loop, erro no UNIX
$ cat numeros.txt | sed ':a ; N ; s/\n/@@@/; b a'
$ cat numeros.txt | sed ':a ; $!N ; s/\n/@@@/; t a' # tudo numa linha
$ cat numeros.txt | sed ':a ; $!N ; s/\n/@@@/; t a ; s/@@@/###/g'
$ cat numeros.txt | tr -d '\n'
$ cat numeros.txt | tr '\n' @
$ cat numeros.txt | sed '1h;$g' # troque a última pela 1a
$ cat numeros.txt | sed '1h;$G' # repete a 1a no final
$ cat numeros.txt | sed '1s/:/@/;1h;$G'
$ cat numeros.txt | sed '1{h;s/:/@/g;x;} ; $G'
$ echo '1{h;s/:/@/g;x;} ; $G' > script.sed
$ vi script.sed # pode alinhar, comentar
$ cat numeros.txt | sed -f script.sed # usar o -f
$ sed -f script.sed numeros.txt # com ou sem o cat
$ chmod +x script.sed # pode ser executável
$ ./script.sed numeros.txt # coloque #!/bin/sed -f
$ mv script.sed meuprog # extensão é opcional
$ ./meuprog numeros.txt
$ cat numeros.txt | sed = # mostra número da linha
$ cat numeros.txt | sed 5=
$ cat numeros.txt | wc -l
$ cat numeros.txt | sed -n '$=' # idem anterior
As Expressões Regulares são uma simbologia, um método de se descrever padrões de texto complicados ou posicionais, como "números no final da linha" ou "palavras repetidas na mesma linha".
$ cat numeros.txt | grep e # procure e
$ cat numeros.txt | grep 'e$' # procure e no fim
$ cat numeros.txt | grep '^1' # procure 1 no início
$ cat numeros.txt | grep '^$' # linhas em branco
$ cat numeros.txt | grep '[eo]$' # e ou o no fim
$ cat numeros.txt | grep '[aeiou]$' # vogais no fim
$ cat numeros.txt | grep '^[aeiou]' # vogais no início
$ cat numeros.txt | cut -d: -f2- # só as palavras
$ cat numeros.txt | cut -d: -f2- | grep '^[aeiou]'
$ cat numeros.txt | cut -d: -f2- | grep '^[aeiouuifduieuifg]'
$ cat numeros.txt | cut -d: -f2- | grep '^[aaaa]'
$ cat numeros.txt | cut -d: -f2- | grep '^[a-z]' # intervalo
$ cat numeros.txt | cut -d: -f2- | grep '^[#-@]'
$ cat numeros.txt | grep '^[a-z]' # letras no início
$ cat numeros.txt | grep '^[0-9]' # números no início
$ cat numeros.txt | grep '^[0-9][0-9]' # dois números no início
$ cat numeros.txt | grep '^[0-9]:[aeiou]' # número:vogal
$ cat numeros.txt | grep '^[0-9]:[^aeiou]' # número:não vogal
$ cat numeros.txt | grep '^[0-9]:[aeiou^-]' # número:vogal ou ^ ou -
$ cat numeros.txt | egrep '^[0-9]{1,}:' # um ou mais números
$ cat numeros.txt | egrep '^[0-9]{1,5}:' # de 1 a 5 números
$ cat numeros.txt | egrep '^[0-9]{2}:' # exatamente 2 números
$ cat numeros.txt | grep '^[0-9]\{2\}:' # _e_grep não escapa
$ cat numeros.txt | grep '^[0-9]:.[aeiou]' # núm : qqr vogal
$ cat numeros.txt | grep '^[0-9]:..[aeiou]' # núm : qqr qqr vogal
$ cat numeros.txt | grep '^[0-9]:...[aeiou]' # núm : qqr qqr qqr vogal
$ cat numeros.txt | grep '\.' # ponto literal
$ cat numeros.txt | grep '^.........[aeiou]' # vários pontos
$ cat numeros.txt | egrep '^.{9}[aeiou]' # 10a é vogal
$ cat numeros.txt | egrep '^.{7,9}[aeiou]' # 8a, 9a ou 10a é vogal
$ cat numeros.txt | egrep '^.{9,}[aeiou]' # 10a em diante é vogal
$ cat numeros.txt | egrep '^.{10}$' # linha com 10 letras
$ cat numeros.txt | egrep '^.{1,10}$' # linha com até 10 letras
$ cat numeros.txt | egrep '^.{10,}$'' # linha com mín 10 letras
$ cat numeros.txt | egrep '[aeiou]..$' # antepenúltima é vogal
$ ? == {0,1} * == {0,} + == {1,}
$ cat numeros.txt | egrep 'X' # X uma vez
$ cat numeros.txt | egrep 'X*' # X zero ou mais vezes
$ cat numeros.txt | egrep 'X+' # X uma ou mais vezes
$ cat numeros.txt | egrep 'X?' # X opcional (0 ou 1)
$ echo aulas | egrep 'aulas?$' # aula ou aulas no fim
$ echo aula | egrep 'aulas?$'
$ echo aulas | egrep '(aulas)?$' # aulas no fim ou não
$ cat ip # ER pra casar IP
10.0.0.1
192.168.255.255
$ cat ip | egrep '^([0-9]{1,3}\.){4}$' # não funciona
$ cat ip | egrep '^([0-9]{1,3}\.){3}[0-9]{3}$' # quase
$ cat ip | egrep '^([0-9]{1,3}\.){3}[0-9]{1,3}$' # ok!
$ seq 260 # olhe a evolução
$ seq 260 | egrep -v '^[0-9]$'
$ seq 260 | egrep -v '^[0-9]{2}$'
$ seq 260 | egrep -v '^[0-9]{1,2}$'
$ seq 260 | egrep -v '^([0-9]{1,2}|1[0-9][0-9])$'
$ seq 260 | egrep -v '^([0-9]{1,2}|1[0-9][0-9]|2[0-5][0-5])$'
$ seq 260 | egrep -v '^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9])$'
$ seq 260 | egrep -v '^([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$'
$ cat ip | egrep '^(([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$'
$ ##### usando variáveis fica mais claro
$ de0a255='([0-9]{1,2}|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
$ cat ip | egrep "^($de0a255\.){3}$de0a255$'
$ echo isso | sed 's/isso|aquilo/XXX/' # isso ou aquilo
$ echo aquilo| sed 's/isso|aquilo/XXX/'
$ echo aquilo| sed 's/\(iss\|aquil\)o/XXX/' # isso ou aquilo
$ echo aquilo| sed -r 's/(iss|aquil)o/XXX/' # com -r, não escapa
$ echo a:a:a:a:a:a | sed 's/a:.*:/X/'
$ echo "<b>abc</b> foo bar <b>xyz</b> XXX" | sed 's,<b>.*</b>,,'
$ echo abcdefg | sed -r 's/(a)(b)(c)/\3:\2:\1/'
$ echo abcdefg | sed -r 's/(a)(b)(c).*/\1:\2:\3/'
$ echo abcdefg | sed -r 's/(a)(b)(c).*/\3:\2:\1/'
$ cat numeros.txt | sed -r 's/^(.*):(.*):(.*)/\3 \2 \1/'
$ seq 99 | egrep '[0-9]{2}' # não é isso
$ seq 99 | egrep '([0-9])\1' # ok!
$ echo quero quero | egrep '([a-z]+) \1' # casou
$ echo quero aula | egrep '([a-z]+) \1' # não casa
$ echo quero aula agora, eu quero | egrep '([a-z]{3,}) .*\1'