{"id":701,"date":"2011-10-10T16:20:50","date_gmt":"2011-10-10T19:20:50","guid":{"rendered":"http:\/\/www.eriberto.pro.br\/blog\/?p=701"},"modified":"2011-10-10T16:20:50","modified_gmt":"2011-10-10T19:20:50","slug":"programacao-shell-a-influencia-do-ambiente-bash-nos-comandos-emitidos-pelo-usuario","status":"publish","type":"post","link":"https:\/\/eriberto.pro.br\/blog\/2011\/10\/10\/programacao-shell-a-influencia-do-ambiente-bash-nos-comandos-emitidos-pelo-usuario\/","title":{"rendered":"Programa\u00e7\u00e3o shell: a influ\u00eancia do ambiente Bash nos comandos emitidos pelo usu\u00e1rio"},"content":{"rendered":"<p>Bem, este \u00e9 mais um daqueles posts que estou h\u00e1 muito tempo para escrever. Trata-se de algo simples mas que muitos desconhecem (inclusive quem j\u00e1 programa em shell).<\/p>\n<p>Muitas vezes queremos criar um script e, mesmo parecendo simples, algo d\u00e1 errado. Quer ver? Fa\u00e7a um teste. Reinicie o seu computador (para limpar o conte\u00fado de \/tmp) e digite:<\/p>\n<pre># cd \/tmp\r\n# ls \/etc | grep lo*<\/pre>\n<p>Depois, execute o mesmo comando dentro de \/etc. Para isso, fa\u00e7a assim:<\/p>\n<pre># cd \/etc\r\n# ls \/etc | grep lo*<\/pre>\n<p>Bem, voc\u00ea deve ter notando uma grotesca diferen\u00e7a. Mas o que ser\u00e1 que ocorreu? \u00c9 a influ\u00eancia do Bash.<\/p>\n<p>O Bash est\u00e1 entre a linha emitida pelo usu\u00e1rio e a execu\u00e7\u00e3o pelo comando em si. Isso pode ser entendido com a figura a seguir.<\/p>\n<p style=\"text-align: center;\"><a href=\"http:\/\/www.eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-medium wp-image-705 aligncenter\" title=\"post_shell\" src=\"http:\/\/www.eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell-189x300.png\" alt=\"\" width=\"189\" height=\"300\" srcset=\"https:\/\/eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell-189x300.png 189w, https:\/\/eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell.png 243w\" sizes=\"auto, (max-width: 189px) 100vw, 189px\" \/><\/a><\/p>\n<p>Repare que todas as ordens do usu\u00e1rio passam pelo Bash. Com isso, h\u00e1 uma interpreta\u00e7\u00e3o intermedi\u00e1ria. Por exemplo: considere um arquivo, chamado lista.txt, com o seguinte conte\u00fado:<\/p>\n<pre>alho\r\ncebola\r\n(alface)\r\ntomate<\/pre>\n<p>Digamos que voc\u00ea queira ver somente as linhas que contenham um par\u00eanteses. A solu\u00e7\u00e3o imediata seria:<\/p>\n<pre>$ grep  (  lista.txt<\/pre>\n<p>No entanto, o seguinte erro surgiria:<\/p>\n<pre>bash: erro de sintaxe pr\u00f3ximo do `token' n\u00e3o esperado `lista.txt'<\/pre>\n<p>Observe com aten\u00e7\u00e3o: o erro foi reportado pelo Bash e n\u00e3o pelo comando grep. Ent\u00e3o, a ordem do usu\u00e1rio nem chegou no grep! Isso ocorreu porque, para o Bash, o par\u00eanteses tem um formato de uso especial e que faz sentido para ele. Uma solu\u00e7\u00e3o \u00e9 fazer o Bash tratar o par\u00eanteses como um caractere comum e n\u00e3o como um caractere especial de opera\u00e7\u00e3o. Uma contrabarra resolve o problema. Veja:<\/p>\n<pre>$ grep  \\(  lista.txt\r\n(alface)<\/pre>\n<p>A contrabarra serve para determinar que o pr\u00f3ximo caractere n\u00e3o tenha interpreta\u00e7\u00e3o especial. Ou seja: trata-se de um caractere simples. Quando adicionamos a contrabarra, o Bash pensa: devo tratar o par\u00eanteses como um caractere qualquer, sem sentido especial para mim. Ent\u00e3o, vem a m\u00e1gica: ele retira a contrabarra e passa somente o par\u00eanteses para o grep. Veja:<\/p>\n<p><a href=\"http:\/\/www.eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-712\" title=\"post_shell_3\" src=\"http:\/\/www.eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_3-221x300.png\" alt=\"\" width=\"221\" height=\"300\" srcset=\"https:\/\/eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_3-221x300.png 221w, https:\/\/eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_3.png 284w\" sizes=\"auto, (max-width: 221px) 100vw, 221px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Agora vamos a um caso mais interessante. Imagine que uma linha termine com um ponto. Veja:<\/p>\n<pre>alho\r\ncebola\r\nalface.\r\ntomate<\/pre>\n<p>Digamos que queiramos ver somente a linha que cont\u00e9m um ponto. A primeira ideia:<\/p>\n<pre>$ grep . lista.txt<\/pre>\n<p>O resultado seria:<\/p>\n<pre>alho\r\ncebola\r\nalface.\r\ntomate<\/pre>\n<p>Isso ocorreu porque para o grep, que usa express\u00f5es regulares, o ponto representa &#8220;qualquer caractere&#8221; e casa com todas as linhas, pois todas t\u00eam, pelo menos, um caractere. Assim, surge a ideia de proteger o ponto com uma contrabarra. Vamos testar:<\/p>\n<pre>$ grep \\. lista.txt\r\nalho\r\ncebola\r\nalface.\r\ntomate<\/pre>\n<p>Novamente n\u00e3o deu certo. Mas porqu\u00ea? Simples! Para o shell, contrabarra quer dizer: n\u00e3o interprete o pr\u00f3ximo caractere como algo especial (que seria um metacaractere). Ent\u00e3o, ele retira a contrabarra e repassa o restante para o grep. Veja:<\/p>\n<p><a href=\"http:\/\/www.eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-716\" title=\"post_shell_4\" src=\"http:\/\/www.eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_4-220x300.png\" alt=\"\" width=\"220\" height=\"300\" srcset=\"https:\/\/eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_4-220x300.png 220w, https:\/\/eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_4.png 282w\" sizes=\"auto, (max-width: 220px) 100vw, 220px\" \/><\/a><\/p>\n<p>A solu\u00e7\u00e3o \u00e9 adicionar outra contrabarra, que ir\u00e1 proteger a segunda. Veja:<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/www.eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_5.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-medium wp-image-717\" title=\"post_shell_5\" src=\"http:\/\/www.eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_5-228x300.png\" alt=\"\" width=\"228\" height=\"300\" srcset=\"https:\/\/eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_5-228x300.png 228w, https:\/\/eriberto.pro.br\/blog\/wp-content\/uploads\/2011\/10\/post_shell_5.png 293w\" sizes=\"auto, (max-width: 228px) 100vw, 228px\" \/><\/a><\/p>\n<p>Na nova situa\u00e7\u00e3o, o shell viu a primeira contrabarra e pensou: &#8220;devo tratar o pr\u00f3ximo caractere, que \u00e9 uma contrabarra, como um caractere comum&#8221;. Como isso, a contrabarra, protegendo o caractere ponto, chega ao grep.<\/p>\n<p>Para terminar, o que ocorreu no comando que abriu este post? Simples:<\/p>\n<pre># cd \/tmp\r\n# ls \/etc | grep lo*<\/pre>\n<p>Estando no \/tmp, foi dado o comando ls com grep. Ao passar pelo shell, o mesmo interpreta &#8220;lo*&#8221; como sendo qualquer arquivo iniciado com lo. Como n\u00e3o h\u00e1 nenhum, ele repassa &#8220;lo*&#8221; para o grep e pronto. No entanto, em:<\/p>\n<pre># cd \/etc\r\n# ls \/etc | grep lo*<\/pre>\n<p>h\u00e1 uma s\u00e9rie de arquivos iniciados com lo. Ent\u00e3o, o shell substitui o &#8220;lo*&#8221; pelos nomes desses arquivos e envia para o grep e a confus\u00e3o est\u00e1 feita. Isso pode ser visto com o comando bash -x, que nos fornece um ambiente interativo que mostra como o bash est\u00e1 raciocinado. Veja:<\/p>\n<pre># bash -x\r\n# cd \/tmp\r\n# ls \/etc | grep lo*\r\n<strong>+ ls \/etc<\/strong>\r\n<strong>+ grep 'lo*<\/strong>'\r\nalternatives\r\nbash_completion.d\r\nbindresvport.blacklist\r\n[...]<\/pre>\n<p>Agora, indo para o \/etc:<\/p>\n<pre># cd \/etc\r\n# ls \/etc | grep lo*\r\n<strong>+ ls \/etc<\/strong>\r\n<strong>+ grep locale.alias locale.gen localtime logcheck login.defs logrotate.conf logrotate.d<\/strong><\/pre>\n<p>Entendeu?<\/p>\n<p>O comando anterior daria certo da seguinte forma:<\/p>\n<pre># ls \/etc | grep lo\\*\r\n<strong>+ ls \/etc<\/strong>\r\n<strong>+ grep 'lo*'<\/strong>\r\nalternatives\r\nbash_completion.d\r\nbindresvport.blacklist\r\nblkid.tab<\/pre>\n<p>Quem programa em shell sabe que tudo que \u00e9 colocado entre ap\u00f3strofos tamb\u00e9m fica protegido. Ent\u00e3o, tamb\u00e9m valeria:<\/p>\n<p># ls \/etc | grep lo&#8217;*&#8217;<\/p>\n<p>ou<\/p>\n<pre># ls \/etc | grep 'lo*'<\/pre>\n<p>Apenas para terminar, para sair do ambiente interativo do shell, digite quit.<\/p>\n<p>Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Bem, este \u00e9 mais um daqueles posts que estou h\u00e1 muito tempo para escrever. Trata-se de algo simples mas que muitos desconhecem (inclusive quem j\u00e1 programa em shell). Muitas vezes queremos criar um script e, mesmo parecendo simples, algo d\u00e1 errado. Quer ver? Fa\u00e7a um teste. Reinicie o seu computador (para limpar o conte\u00fado de&hellip;&nbsp;<a href=\"https:\/\/eriberto.pro.br\/blog\/2011\/10\/10\/programacao-shell-a-influencia-do-ambiente-bash-nos-comandos-emitidos-pelo-usuario\/\" rel=\"bookmark\">Continue a ler &raquo;<span class=\"screen-reader-text\">Programa\u00e7\u00e3o shell: a influ\u00eancia do ambiente Bash nos comandos emitidos pelo usu\u00e1rio<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[3,14,11],"tags":[621,284,226,283],"class_list":["post-701","post","type-post","status-publish","format-standard","hentry","category-linux","category-shell","category-sistema-operacional","tag-linux","tag-programacao","tag-shell-2","tag-shell-script"],"_links":{"self":[{"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/posts\/701","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/comments?post=701"}],"version-history":[{"count":0,"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/posts\/701\/revisions"}],"wp:attachment":[{"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/media?parent=701"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/categories?post=701"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eriberto.pro.br\/blog\/wp-json\/wp\/v2\/tags?post=701"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}