Bem-vindos à segunda parte da nossa série, uma parte que se centrará no sed, a versão GNU. Como verão, existem várias variantes de sed, que está disponível para bastantes plataformas, mas concentrar-nos-emos nas versões 4.x do GNU sed. Muitos de vós já ouviram falar do sed e já o utilizaram, principalmente como uma ferramenta de substituição. Mas isso é apenas um segmento do que o sed pode fazer, e faremos o nosso melhor para vos mostrar o máximo possível do que podem fazer com ele. O nome significa Stream EDitor, e aqui “stream” pode ser um ficheiro, um cano ou simplesmente stdin. Esperamos que tenha conhecimentos básicos de Linux e, se já trabalhou com expressões regulares ou pelo menos sabe o que é uma regexp, tanto melhor. Não temos espaço para um tutorial completo sobre expressões regulares, por isso, em vez disso, dar-lhe-emos apenas uma ideia básica e muitos exemplos de sed. Há muitos documentos que tratam do assunto, e até teremos algumas recomendações, como verá dentro de um minuto.
Instalação
Não há muito a dizer aqui, porque provavelmente já tem o sed instalado, porque é utilizado em vários scripts de sistema e é uma ferramenta inestimável na vida de um utilizador de Linux que quer ser eficiente. Pode testar que versão tem, digitando
$ sed --version
No meu sistema, este comando diz-me que tenho o GNU sed 4.2.1 instalado, mais links para a página inicial e outras coisas úteis. O pacote é nomeado simplesmente ‘sed’ independentemente da distribuição, mas se o Gentoo oferece sed implicitamente, acredito que isso significa que pode ficar descansado.
Conceitos
Antes de irmos mais longe, sentimos que é importante apontar o que é que o sed faz exactamente, porque o “editor de fluxo” pode não tocar demasiados sinos. sed pega no texto de entrada, faz as operações especificadas em cada linha (salvo especificação em contrário) e imprime o texto modificado. As operações especificadas podem ser anexadas, inseridas, apagadas ou substituídas. Isto não é tão simples como pode parecer: esteja avisado que existem muitas opções e combinações que podem tornar um comando sed bastante difícil de digerir. Assim, se quiser usar o sed, recomendamos que aprenda o básico de regexps, e pode apanhar o resto à medida que avança. Antes de iniciarmos o tutorial, queremos agradecer a Eric Pement e outros pela inspiração e pelo que ele fez por todos os que querem aprender e usar sed.
O Instituto Geofísico UAF, está à procura de um Analista de Sistemas Linux experiente para se juntar à sua equipa de analistas e engenheiros de infra-estruturas cibernéticas de pesquisa. LOCALIZAÇÃO: Fairbanks, Alasca, EUA
APPLY NOW
/div>
Expressões regulamentares
Como os comandos/escritos sed tendem a tornar-se crípticos, sentimos que os nossos leitores devem compreender os conceitos básicos em vez de copiar e colar cegamente os comandos de que não conhecem o significado. Quando se quer compreender o que é uma regexp, a palavra-chave é “correspondência”. Ou ainda melhor, “correspondência de padrões”. Por exemplo, num relatório para o seu departamento de RH, escreveu o nome de Nick quando se referia ao arquitecto da rede. Mas Nick seguiu em frente e John veio ocupar o seu lugar, por isso agora tem de substituir a palavra Nick por John. Se o ficheiro se chamar report.txt, poderá fazer
$ cat report.txt | sed 's/Nick/John/g' > report_new.txt
Por defeito, o sed usa stdout, pelo que poderá querer usar o operador de redireccionamento do seu shell, como no nosso exemplo abaixo. Este é um exemplo muito simples, mas nós ilustramos alguns pontos: combinamos o padrão “Nick” e substituímos todas as instâncias por “John”. Note que o sed é sensível a maiúsculas e minúsculas, por isso tenha cuidado e verifique o seu ficheiro de saída para ver se todas as substituições foram feitas. O acima referido também poderia ter sido escrito assim:
$ sed 's/Nick/John/g' report.txt > report_new.txt
OK, mas onde estão as expressões regulares, perguntam vocês? Bem, primeiro queríamos molhar os pés com o conceito de correspondência e aqui vem a parte interessante.
Se não tiver a certeza se escreveu “nick” por engano em vez de “Nick” e quiser corresponder também, poderia usar sed ‘s/Nick|nick/John/g’. A barra vertical tem o mesmo significado que poderia saber se usasse C, ou seja, a sua expressão corresponderia a Nick ou nick. Como verá, o tubo também pode ser usado de outras formas, mas o seu significado permanecerá. Outros operadores amplamente utilizados em regexps são “?”, que correspondem a zero ou a uma instância do elemento anterior (flavou?r irá corresponder ao sabor e sabor), ‘*’ significa zero ou mais e ‘+’ corresponde a um ou mais elementos. ‘^’ corresponde ao início da cadeia, enquanto ‘ Se for um utilizador do vi(m), algumas destas coisas podem parecer-lhe familiares. Afinal, estas utilidades, juntamente com awk ou C têm as suas raízes nos primeiros dias do Unix. Não insistiremos mais no assunto, pois as coisas tornar-se-ão mais simples através da leitura de exemplos, mas o que deve saber é que existem várias implementações de regexps: POSIX, POSIX Estendido, Perl ou várias implementações de expressões regulares difusas, com a garantia de lhe dar uma dor de cabeça.
sed examples
Sintaxe do comando Linux | Descrição do comando Linux |
---|---|
sed 's/Nick/John/g' report.txt |
Substituir cada ocorrência de Nick por John no relatório.txt |
sed 's/Nick|nick/John/g' report.txt |
Substituir todas as ocorrências de Nick ou nick por John. |
sed 's/^/ /' file.txt >file_new.txt |
Adicionar 8 espaços à esquerda de um texto para impressão bonita. |
sed -n '/Of course/,/attention you \ |
Exibe apenas um parágrafo, começando por “Claro” e terminando em “atenção que presta” |
sed -n 12,18p file.txt |
Mostrar apenas linhas 12-18 de ficheiro.txt |
sed 12,18d file.txt |
Mostrar todo o ficheiro.txt excepto para linhas de 12 a 18 |
sed G file.txt |
Arquivo de espaço duplo.txt |
sed -f script.sed file.txt |
Escrever todos os comandos em script.sed e executá-los |
sed '5!s/ham/cheese/' file.txt |
Substituir presunto por queijo em ficheiro.txt excepto na 5ª linha |
sed '$d' file.txt |
Delete a última linha |
sed '/\{3\}/p' file.txt |
Imprimir apenas linhas com três dígitos consecutivos |
sed '/boom/!s/aaa/bb/' file.txt |
Encontra-se um boom sem aaa por bb |
sed '17,/disk/d' file.txt |
Delete todas as linhas da linha 17 para ‘disk’ |
echo ONE TWO | sed "s/one/unos/I" |
Substitui uma por unos num casomaneira insensível, para imprimir “unos TWO” |
sed 'G;G' file.txt |
Triplo…espaçar um ficheiro |
sed 's/.$//' file.txt |
Uma forma de substituir dos2unix 🙂 |
sed 's/^*//' file.txt |
Delete todos os espaços em frente de cada linha de ficheiro.txt |
sed 's/*$//' file.txt |
Eliminar todos os espaços no fim de cada linha de ficheiro.txt |
sed 's/^*//;s/*$//' file.txt |
Eliminar todos os espaços em frente e no fim de cada linha de ficheiro.txt |
sed 's/foo/bar/' file.txt |
Substituir foo por barra apenas para a primeira instância numa linha. |
sed 's/foo/bar/4' file.txt |
Substituir foo por barra apenas para a 4ª instância numa linha. |
sed 's/foo/bar/g' file.txt |
Substituir foo por barra para todas as instâncias numa linha. |
sed '/baz/s/foo/bar/g' file.txt |
Apenas se a linha contiver baz, substituir foo por bar |
sed '/./,/^$/!d' file.txt |
Delete all consecutive blank linhas excepto para EOF |
sed '/^$/N;/\n$/D' file.txt |
Eliminar todas as linhas em branco consecutivas, mas permite apenas a linha superior em branco |
sed '/./,$!d' file.txt |
Delete all leading blank lines |
sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' \ |
Delete all trailing blank lines |
sed -e :a -e '/\$/N; s/\\n//; ta' \ |
Se um ficheiro terminar numa barra invertida, juntá-lo com o próximo (útil para shell scripts) |
sed '/regex/,+5/expr/' |
Match regex plus the next 5 lines |
sed '1~3d' file.txt |
Delete cada terceira linha, começando com a primeira |
sed -n '2~5p' file.txt |
Imprima cada 5ª linha começando com the second |
sed 's/ick/John/g' report.txt |
Outra forma de escrever algum exemplo acima. P>Pode adivinhar qual deles? |
sed -n '/RE/{p;q;}' file.txt |
Imprimir apenas a primeira correspondência de RE (expressão regular) |
sed '0,/RE/{//d;}' file.txt |
Delete only the first match |
sed '0,/RE/s//to_that/' file.txt |
Alterar apenas a primeira partida |
sed 's/^*,/9999,/' file.csv |
Alterar primeiro campo para 9999 num ficheiro CSV |
s/^ *\(.*\) *$/||/; |
sed script para converter ficheiro CSV para bar-separado (funciona apenas em alguns tipos de CSV, com “s e vírgulas) |
sed ':a;s/\(^\|\)\(\+\)\ |
Alterar números do ficheiro.txt do formulário 1234.56 para 1.234.56 |
sed -r "s/\<(reg|exp)+/\U&/g" |
Converter qualquer palavra começando com reg ou exp para maiúsculas |
sed '1,20 s/Johnson/White/g' file.txt |
P>Substituir Johnson por Branco apenas em linhas entre 1 e 20 |
sed '1,20 !s/Johnson/White/g' file.txt |
O acima invertido (corresponder a todos excepto as linhas 1-20) |
sed '/from/,/until/ { s/\<red\>/magenta/g; \ |
Substituir apenas entre “de” e até” |
sed '/ENDNOTES:/,$ { s/Schaff/Herzog/g; \ |
Substituir apenas da palavra “ENDNOTES”:” até EOF |
sed '/./{H;$!d;};x;/regex/!d' file.txt |
Imprimir parágrafos apenas se contiverem regex |
sed -e '/./{H;$!d;}' -e 'x;/RE1/!d;\ |
Imprimir parágrafos apenas se contiverem RE1, RE2 e RE3 |
sed ':a; /\$/N; s/\\n//; ta' file.txt |
Junte duas linhas no primeiro termina numa barra invertida |
sed 's/14"/fourteen inches/g' file.txt |
É assim que você pode usar aspas duplas |
sed 's/\/some\/UNIX\/path/\/a\/new\ |
Trabalhar com Unix paths |
sed 's///g' file.txt |
Remover todos os caracteres de a a a g de ficheiro.txt |
sed 's/\(.*\)foo/bar/' file.txt |
Substituir apenas a última partida de foo com bar |
sed '1!G;h;$!d' |
A tac replacement |
sed '/\n/!G;s/\(.\)\(.*\n\)/&\ |
Uma substituição rev |
sed 10q file.txt |
Uma substituição de cabeça |
sed -e :a -e '$q;N;11,$D;ba' \ |
Um substituto de cauda |
sed '$!N; /^\(.*\)\n$/!P; D' \ |
A unq replacement |
O oposto (ou uniq -d equivalent) | |
sed '$!N;$!D' file.txt |
Equivalente à cauda -n 2 |
sed -n '$p' file.txt |
… cauda -n 1 (ou cauda -1) |
sed '/regexp/!d' file.txt |
equivalente de grepa |
sed -n '/regexp/{g;1!p;};h' file.txt |
Imprimir a linha antes da regexp correspondente, mas não a que contém a regexp |
sed -n '/regexp/{n;p;}' file.txt |
Imprimir a linha após a que corresponde à regexp, mas
não a que contém a regexp |
sed '/pattern/d' file.txt |
Delete lines matching pattern |
sed '/./!d' file.txt |
Delete todas as linhas em branco de a file |
sed '/^$/N;/\n$/N;//D' file.txt |
Eliminar todas as linhas em branco consecutivas excepto para as duas primeiras |
sed -n '/^$/{p;h;};/./{x;/./p;}'\ |
Delete a última linha de cada paragraph |
sed 's/.\x08//g' file |
Remover nroff overstrikes |
sed '/^$/q' |
Get mail header |
sed '1,/^$/d' |
Get mail body |
sed '/^Subject: */!d; s///;q' |
Get mail subject |
sed 's/^/> /' |
Mensagem de correio de cotação inserindo uma “> ” em frente de cada linha |
sed 's/^> //' |
O oposto (mensagem de correio sem aspas) |
sed -e :a -e 's/<*>//g;/</N;//ba' |
Remover tags HTML |
sed '/./{H;d;};x;s/\n/={NL}=/g'\ |
Classificar parágrafos de ficheiro.txt alfabeticamente |
sed 's@/usr/bin@&/local@g' path.txt |
Substituir /usr/bin por /usr/bin/local no caminho.txt |
sed 's@^.*$@<<<&>>>@g' path.txt |
Tente e veja 🙂 |
sed 's/\(\/*\).*//g' path.txt |
Caminho fornecido.txt contém $PATH, isto irá echo apenas o primeiro caminho em cada linha |
sed 's/\(*\).*//' /etc/passwd |
substituição doawk – mostra apenas os utilizadores do ficheiro passwd |
echo "Welcome To The Geek Stuff" | sed \ |
Selff-explicativo |
sed -e '/^$/,/^END/s/hills/\ |
Swap ‘montes’ para ‘montanhas’, mas apenas em blocos de texto começando com uma linha em branco, e terminando com uma linha começando com os três caracteres ‘END’, inclusive |
sed -e '/^#/d' /etc/services | more |
Ver o ficheiro de serviços sem o comentado lines |
sed '$s@\(*\):\(*\):\(*\ |
Ordem inversa dos itens na última linha do caminho.txt |
sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}'\ |
Imprimir 1 linha de contexto antes e depois da correspondência de linha, com um número de linha onde ocorre a correspondência |
sed '/regex/{x;p;x;}' ficheiro.txt |
Inserir uma nova linha acima de cada linha correspondente a regex |
sed '/AAA/!d; /BBB/!d; /CCC/!d' file.txt |
Match AAA, BBB e CCC em qualquer ordem |
sed '/AAA.*BBB.*CCC/!d' file.txt |
Match AAA, BBB e CCC nessa ordem |
sed -n '/^.\{65\}/p' file.txt |
Print lines 65 chars long or more |
sed -n '/^.\{65\}/!p' file.txt |
Print lines 65 chars long or less |
sed '/regex/G' file.txt |
Inserir linha em branco abaixo de cada linha |
sed ficheiro '/regex/{x;p;x;G;}'.txt |
Inserir linha em branco acima e abaixo |
sed = ficheiro.txt | sed 'N;s/\n/\t/' |
Linhas numéricas em ficheiro.txt |
sed -e :a -e 's/^.{1,78\}$/^.{1,78\}br>&/;ta' ficheiro.txt |
align text flush right |
sed -e :a -e 's/^.\{1,77\}$/ &/;ta' -e {\i}br>'s/( *\i)//' file.txt |
Align text center |
Conclusion
Isto é apenas uma parte do que pode ser dito sobre o sed, mas esta série pretende ser um guia prático, por isso esperamos que o ajude a descobrir o poder das ferramentas Unix e a tornar-se mais eficiente no seu trabalho.
faz o oposto. If you’re a vi(m) user, some of these things might look familiar. After all, these utilities, together with awk or C have their roots in the early days of Unix. We won’t insist anymore on the subject, as things will become simpler by reading examples, but what you should know is that there are various implementations of regexps: POSIX, POSIX Extended, Perl or various implementations of fuzzy regular expressions, guaranteed to give you a headache.
sed examples
Learning Linux sed command with examples | |
---|---|
Linux command syntax | Linux command description |
sed 's/Nick/John/g' report.txt |
Replace every occurrence of Nick with John in report.txt |
sed 's/Nick|nick/John/g' report.txt |
Replace every occurrence of Nick or nick with John. |
sed 's/^/ /' file.txt >file_new.txt |
Add 8 spaces to the left of a text for pretty printing. |
sed -n '/Of course/,/attention you \ |
Display only one paragraph, starting with “Of course” and ending in “attention you pay” |
sed -n 12,18p file.txt |
Show only lines 12-18 of file.txt |
sed 12,18d file.txt |
Show all of file.txt except for lines from 12 to 18 |
sed G file.txt |
Double-space file.txt |
sed -f script.sed file.txt |
Write all commands in script.sed and execute them |
sed '5!s/ham/cheese/' file.txt |
Replace ham with cheese in file.txt except in the 5th line |
sed '$d' file.txt |
Delete the last line |
sed '/\{3\}/p' file.txt |
Print only lines with three consecutive digits |
sed '/boom/!s/aaa/bb/' file.txt |
Unless boom is found replace aaa with bb |
sed '17,/disk/d' file.txt |
Delete all lines from line 17 to ‘disk’ |
echo ONE TWO | sed "s/one/unos/I" |
Replaces one with unos in a case-insensitive manner, so it will print “unos TWO” |
sed 'G;G' file.txt |
Triple-space a file |
sed 's/.$//' file.txt |
A way to replace dos2unix 🙂 |
sed 's/^*//' file.txt |
Delete all spaces in front of every line of file.txt |
sed 's/*$//' file.txt |
Delete all spaces at the end of every line of file.txt |
sed 's/^*//;s/*$//' file.txt |
Delete all spaces in front and at the end of every line of file.txt |
sed 's/foo/bar/' file.txt |
Replace foo with bar only for the first instance in a line. |
sed 's/foo/bar/4' file.txt |
Replace foo with bar only for the 4th instance in a line. |
sed 's/foo/bar/g' file.txt |
Replace foo with bar for all instances in a line. |
sed '/baz/s/foo/bar/g' file.txt |
Only if line contains baz, substitute foo with bar |
sed '/./,/^$/!d' file.txt |
Delete all consecutive blank lines except for EOF |
sed '/^$/N;/\n$/D' file.txt |
Delete all consecutive blank lines, but allows only top blank line |
sed '/./,$!d' file.txt |
Delete all leading blank lines |
sed -e :a -e '/^\n*$/{$d;N;};/\n$/ba' \ |
Delete all trailing blank lines |
sed -e :a -e '/\$/N; s/\\n//; ta' \ |
If a file ends in a backslash, join it with the next (useful for shell scripts) |
sed '/regex/,+5/expr/' |
Match regex plus the next 5 lines |
sed '1~3d' file.txt |
Delete every third line, starting with the first |
sed -n '2~5p' file.txt |
Print every 5th line starting with the second |
sed 's/ick/John/g' report.txt |
Another way to write some example above. Can you guess which one? |
sed -n '/RE/{p;q;}' file.txt |
Print only the first match of RE (regular expression) |
sed '0,/RE/{//d;}' file.txt |
Delete only the first match |
sed '0,/RE/s//to_that/' file.txt |
Change only the first match |
sed 's/^*,/9999,/' file.csv |
Change first field to 9999 in a CSV file |
s/^ *\(.*\) *$/||/; |
sed script to convert CSV file to bar-separated (works only on some types of CSV, with embedded “s and commas) |
sed ':a;s/\(^\|\)\(\+\)\ |
Change numbers from file.txt from 1234.56 form to 1.234.56 |
sed -r "s/\<(reg|exp)+/\U&/g" |
Convert any word starting with reg or exp to uppercase |
sed '1,20 s/Johnson/White/g' file.txt |
Do replacement of Johnson with White only on lines between 1 and 20 |
sed '1,20 !s/Johnson/White/g' file.txt |
The above reversed (match all except lines 1-20) |
sed '/from/,/until/ { s/\<red\>/magenta/g; \ |
Replace only between “from” and “until” |
sed '/ENDNOTES:/,$ { s/Schaff/Herzog/g; \ |
Replace only from the word “ENDNOTES:” until EOF |
sed '/./{H;$!d;};x;/regex/!d' file.txt |
Print paragraphs only if they contain regex |
sed -e '/./{H;$!d;}' -e 'x;/RE1/!d;\ |
Print paragraphs only if they contain RE1, RE2 and RE3 |
sed ':a; /\$/N; s/\\n//; ta' file.txt |
Join two lines in the first ends in a backslash |
sed 's/14"/fourteen inches/g' file.txt |
This is how you can use double quotes |
sed 's/\/some\/UNIX\/path/\/a\/new\ |
Working with Unix paths |
sed 's///g' file.txt |
Remove all characters from a to g from file.txt |
sed 's/\(.*\)foo/bar/' file.txt |
Replace only the last match of foo with bar |
sed '1!G;h;$!d' |
A tac replacement |
sed '/\n/!G;s/\(.\)\(.*\n\)/&\ |
A rev replacement |
sed 10q file.txt |
A head replacement |
sed -e :a -e '$q;N;11,$D;ba' \ |
A tail replacement |
sed '$!N; /^\(.*\)\n$/!P; D' \ |
A uniq replacement |
sed '$!N; s/^\(.*\)\n$//;\ |
The opposite (or uniq -d equivalent) |
sed '$!N;$!D' file.txt |
Equivalent to tail -n 2 |
sed -n '$p' file.txt |
… tail -n 1 (or tail -1) |
sed '/regexp/!d' file.txt |
grep equivalent |
sed -n '/regexp/{g;1!p;};h' file.txt |
Print the line before the one matching regexp, but not the one containing the regexp |
sed -n '/regexp/{n;p;}' file.txt |
Print the line after the one matching the regexp, but
not the one containing the regexp |
sed '/pattern/d' file.txt |
Delete lines matching pattern |
sed '/./!d' file.txt |
Delete all blank lines from a file |
sed '/^$/N;/\n$/N;//D' file.txt |
Delete all consecutive blank lines except for the first two |
sed -n '/^$/{p;h;};/./{x;/./p;}'\ |
Delete the last line of each paragraph |
sed 's/.\x08//g' file |
Remove nroff overstrikes |
sed '/^$/q' |
Get mail header |
sed '1,/^$/d' |
Get mail body |
sed '/^Subject: */!d; s///;q' |
Get mail subject |
sed 's/^/> /' |
Quote mail message by inserting a “> ” in front of every line |
sed 's/^> //' |
The opposite (unquote mail message) |
sed -e :a -e 's/<*>//g;/</N;//ba' |
Remove HTML tags |
sed '/./{H;d;};x;s/\n/={NL}=/g'\ |
Sort paragraphs of file.txt alphabetically |
sed 's@/usr/bin@&/local@g' path.txt |
Replace /usr/bin with /usr/bin/local in path.txt |
sed 's@^.*$@<<<&>>>@g' path.txt |
Try it and see 🙂 |
sed 's/\(\/*\).*//g' path.txt |
Provided path.txt contains $PATH, this will echo only the first path on each line |
sed 's/\(*\).*//' /etc/passwd |
awk replacement – displays only the users from the passwd file |
echo "Welcome To The Geek Stuff" | sed \ |
Self-explanatory |
sed -e '/^$/,/^END/s/hills/\ |
Swap ‘hills’ for ‘mountains’, but only on blocks of text beginning with a blank line, and ending with a line beginning with the three characters ‘END’, inclusive |
sed -e '/^#/d' /etc/services | more |
View the services file without the commented lines |
sed '$s@\(*\):\(*\):\(*\ |
Reverse order of items in the last line of path.txt |
sed -n -e '/regexp/{=;x;1!p;g;$!N;p;D;}'\ |
Print 1 line of context before and after the line matching, with a line number where the matching occurs |
sed '/regex/{x;p;x;}' file.txt |
Insert a new line above every line matching regex |
sed '/AAA/!d; /BBB/!d; /CCC/!d' file.txt |
Match AAA, BBB and CCC in any order |
sed '/AAA.*BBB.*CCC/!d' file.txt |
Match AAA, BBB and CCC in that order |
sed -n '/^.\{65\}/p' file.txt |
Print lines 65 chars long or more |
sed -n '/^.\{65\}/!p' file.txt |
Print lines 65 chars long or less |
sed '/regex/G' file.txt |
Insert blank line below every line |
sed '/regex/{x;p;x;G;}' file.txt |
Insert blank line above and below |
sed = file.txt | sed 'N;s/\n/\t/' |
Number lines in file.txt |
sed -e :a -e 's/^.\{1,78\}$/\ |
Align text flush right |
sed -e :a -e 's/^.\{1,77\}$/ &/;ta' -e \ |
Align text center |
Conclusion
This is only a part of what can be told about sed, but this series is meant as a practical guide, so we hope it helps you discover the power of Unix tools and become more efficient in your work.