Slackjeff Wiki

Juntando bits aprendemos juntos

Ferramentas do usuário

Ferramentas do site


utils:ed

Diferenças

Aqui você vê as diferenças entre duas revisões dessa página.

Link para esta página de comparações

Ambos lados da revisão anteriorRevisão anterior
Próxima revisão
Revisão anterior
utils:ed [2025/01/10 00:42] – [Indo e voltando] ajustes tipográficos hrcerqutils:ed [2025/08/09 19:21] (atual) – [Abrindo e trocando de arquivos] formatação monoespaçada hrcerq
Linha 39: Linha 39:
   * **Dispensa combinações de teclas**   * **Dispensa combinações de teclas**
  
-Por ser um editor multimodal, não é preciso utilizar combinações de teclas usando **Ctrl** **Alt**. O texto não se confunde com os comandos, pois eles são isolados em modos de edição diferentes. Como bônus, os comandos são curtos (apenas um caractere), possivelmente acompanhados de endereços (linhas a editar) e parâmetros. Mais detalhes sobre essa estrutura de comandos serão detalhados adiante.+Por ser um editor multimodal, não é preciso utilizar combinações de teclas usando ''Ctrl'' ''Alt''. O texto não se confunde com os comandos, pois eles são isolados em modos de edição diferentes. Como bônus, os comandos são curtos (apenas um caractere), possivelmente acompanhados de endereços (linhas a editar) e parâmetros. Mais detalhes sobre essa estrutura de comandos serão detalhados adiante.
  
   * **Não possui dependências**   * **Não possui dependências**
  
-Por ser um editor minimalista, o __ed__ não possui outras bibliotecas como dependências (nem mesmo //ncurses// ou //readline//). Ele se basta. Para sistemas minimalistas e hardware com capacidades limitadas, isso é ótimo. Além disso, não possuir dependências significa que não há preocupação com ligação dinâmica, que não é suportada por alguns sistemas operacionais, e que mesmo quando é suportado já envolve algumas preocupações com segurança.+Por ser um editor minimalista, o __ed__ não possui outras bibliotecas como dependências (nem mesmo __ncurses__ ou __readline__). Ele se basta. Para sistemas minimalistas e hardware com capacidades limitadas, isso é ótimo. Além disso, não possuir dependências significa que não há preocupação com ligação dinâmica, que não é suportada por alguns sistemas operacionais, e que mesmo quando é suportado já envolve algumas preocupações com segurança.
  
 Não possuir dependências significa que mesmo em modo monousuário do UNIX ele pode ser utilizado. Não por acaso ele geralmente fica no diretório __/bin__ e não em __/usr/bin__ (em sistemas que ainda levam essa separação a sério). Não possuir dependências significa que mesmo em modo monousuário do UNIX ele pode ser utilizado. Não por acaso ele geralmente fica no diretório __/bin__ e não em __/usr/bin__ (em sistemas que ainda levam essa separação a sério).
Linha 206: Linha 206:
 Ufa! Agora você já sabe encerrar o editor, quando precisar. Mas vou além: o comando ''q'' só vai encerrar o editor mesmo se ele não tiver sofrido nenhuma mudança. Se você tiver feito quaisquer alterações no //buffer//, um alerta será emitido e você terá de usar o comando ''q'' novamente para confirmar que deseja encerrar. Outra opção, se tiver conteúdo não salvo que queira descartar é usar o comando ''Q''. Nesse caso nenhum alerta será emitido e ele será prontamente encerrado. Ufa! Agora você já sabe encerrar o editor, quando precisar. Mas vou além: o comando ''q'' só vai encerrar o editor mesmo se ele não tiver sofrido nenhuma mudança. Se você tiver feito quaisquer alterações no //buffer//, um alerta será emitido e você terá de usar o comando ''q'' novamente para confirmar que deseja encerrar. Outra opção, se tiver conteúdo não salvo que queira descartar é usar o comando ''Q''. Nesse caso nenhum alerta será emitido e ele será prontamente encerrado.
  
-É importante frisar que digitar ''Ctrl+c'' não encerra o editor. Sinais de interrupção apenas emitem uma mensagem de erro (veremos mais sobre mensagens de erro e alertas depois).+É importante frisar que digitar ''Ctrl'' ''c'' não encerra o editor. Sinais de interrupção apenas emitem uma mensagem de erro (veremos mais sobre mensagens de erro e alertas depois).
  
 Agora, um outro ponto que é importante aprender desde cedo é sobre a configuração e uso de um //prompt//. Como falei antes, ele é um meio de evitar a confusão entre o modo de comandos e o modo de entrada. Para iniciar o editor já com o uso de um //prompt// você deve usar o parâmetro ''-p'', como a seguir: Agora, um outro ponto que é importante aprender desde cedo é sobre a configuração e uso de um //prompt//. Como falei antes, ele é um meio de evitar a confusão entre o modo de comandos e o modo de entrada. Para iniciar o editor já com o uso de um //prompt// você deve usar o parâmetro ''-p'', como a seguir:
Linha 241: Linha 241:
 ===== Abrindo e trocando de arquivos ===== ===== Abrindo e trocando de arquivos =====
  
-Já vimos como o editor pode ser aberto e fechado, mas e quanto à seleção dos arquivos que serão editados? Como isso é feito? Existem duas possibilidades: uma é informar o nome de um arquivo logo ao iniciar o editor, portanto na chamada do comando __ed__, passar um arquivo como argumento; outra é abrir o editor com um //buffer// vazio, e em seguida usar o comando **e** para selecionar um arquivo.+Já vimos como o editor pode ser aberto e fechado, mas e quanto à seleção dos arquivos que serão editados? Como isso é feito? Existem duas possibilidades: uma é informar o nome de um arquivo logo ao iniciar o editor, portanto na chamada do comando __ed__, passar um arquivo como argumento; outra é abrir o editor com um //buffer// vazio, e em seguida usar o comando ''e'' para selecionar um arquivo.
  
 A título de exemplo, consideremos um arquivo de texto, contendo o texto: A título de exemplo, consideremos um arquivo de texto, contendo o texto:
Linha 264: Linha 264:
 Logo em seguida o //prompt// aparece, e você pode inserir comandos para ler ou editar o arquivo. Mas calma, ainda chegaremos lá. Por hora, vamos ver mais algumas questões relacionadas ao carregamento do arquivo. Logo em seguida o //prompt// aparece, e você pode inserir comandos para ler ou editar o arquivo. Mas calma, ainda chegaremos lá. Por hora, vamos ver mais algumas questões relacionadas ao carregamento do arquivo.
  
-Digamos que você iniciou o editor com um //buffer// vazio. Você pode então usar o comando **e** para carregar o arquivo. Vejamos:+Digamos que você iniciou o editor com um //buffer// vazio. Você pode então usar o comando ''e'' para carregar o arquivo. Vejamos:
  
 <code> <code>
Linha 277: Linha 277:
 "Espere! Nome do arquivo memorizado? Como assim?" Já imagino que esteja se perguntando. Lembra-se do conceito de nome de arquivo que expliquei antes? Pois bem, ao carregar um arquivo, o __ed__ memoriza o nome dele, para que futuras escritas no //buffer// possam ser feitas sem que você precise informar novamente esse nome como parâmetro. "Espere! Nome do arquivo memorizado? Como assim?" Já imagino que esteja se perguntando. Lembra-se do conceito de nome de arquivo que expliquei antes? Pois bem, ao carregar um arquivo, o __ed__ memoriza o nome dele, para que futuras escritas no //buffer// possam ser feitas sem que você precise informar novamente esse nome como parâmetro.
  
-Ao iniciar o editor com um //buffer// vazio, essa informação não existe. Porém, ao iniciar com um arquivo, ou ao carregar um arquivo, como feito nos exemplos anteriores, essa informação é preenchida, com o nome do arquivo carregado (neste exemplo, "poema_ed.txt").+Ao iniciar o editor com um //buffer// vazio, essa informação não existe. Porém, ao iniciar com um arquivo, ou ao carregar um arquivo, como feito nos exemplos anteriores, essa informação é preenchida, com o nome do arquivo carregado (neste exemplo, //poema_ed.txt//).
  
-Para visualizar o nome memorizado, usamos o comando **f**. Um erro será emitido se o nome não estiver preenchido ainda.+Para visualizar o nome memorizado, usamos o comando ''f''. Um erro será emitido se o nome não estiver preenchido ainda.
  
 <code> <code>
Linha 292: Linha 292:
 </code> </code>
  
-O sinal de interrogação nesse caso indica que houve algum erro (deixemos a interpretação disso para depois). Mas note que depois de carregado o arquivo, o nome passou a existir (ficou memorizado). Podemos a qualquer momento usar esse mesmo comando **f** para trocar esse nome. Isso não renomeia o arquivo carregado, apenas sinaliza para o editor __ed__, que no momento de salvar, ele deverá escrever em outro arquivo.+O sinal de interrogação nesse caso indica que houve algum erro (deixemos a interpretação disso para depois). Mas note que depois de carregado o arquivo, o nome passou a existir (ficou memorizado). Podemos a qualquer momento usar esse mesmo comando ''f'' para trocar esse nome. Isso não renomeia o arquivo carregado, apenas sinaliza para o editor __ed__, que no momento de salvar, ele deverá escrever em outro arquivo.
  
 Retomaremos esse assunto quando tratarmos sobre a operação de escrita. Retomaremos esse assunto quando tratarmos sobre a operação de escrita.
  
-Você pode, a qualquer momento, usar o comando **e** para trocar o arquivo carregado no //buffer// (inclusive para um arquivo que ainda não existe, que será criado ao acionar a operação de escrita).+Você pode, a qualquer momento, usar o comando ''e'' para trocar o arquivo carregado no //buffer// (inclusive para um arquivo que ainda não existe, que será criado ao acionar a operação de escrita).
  
 <code> <code>
Linha 316: Linha 316:
 Apenas lembre-se: se houver quaisquer alterações não salvas, um alerta será emitido. Você pode ignorá-lo e reexecutar o comando, para prosseguir, perdendo as alterações. Apenas lembre-se: se houver quaisquer alterações não salvas, um alerta será emitido. Você pode ignorá-lo e reexecutar o comando, para prosseguir, perdendo as alterações.
  
-Caso já tenha certeza de que não quer salvar nada, pode usar o comando **E** no lugar de **e**, para que nenhum alerta seja emitido e o editor imediatamente prossiga com o carregamento do próximo arquivo.+Caso já tenha certeza de que não quer salvar nada, pode usar o comando ''E'' no lugar de ''e'', para que nenhum alerta seja emitido e o editor imediatamente prossiga com o carregamento do próximo arquivo.
  
-Tanto o comando **e** como o comando **E**, quando não recebem nenhum nome de arquivo como parâmetro, apenas recarregam o arquivo no //buffer// (com ou sem a mensagem de alerta, dependendo de qual deles usar). Isto pode ser útil caso queira apenas recarregar o arquivo descartando todas as alterações que fez, desde a última escrita.+Tanto o comando ''e'' como o comando ''E'', quando não recebem nenhum nome de arquivo como parâmetro, apenas recarregam o arquivo no //buffer// (com ou sem a mensagem de alerta, dependendo de qual deles usar). Isto pode ser útil caso queira apenas recarregar o arquivo descartando todas as alterações que fez, desde a última escrita.
  
 <note> <note>
Linha 373: Linha 373:
  
  
-==== Uma nota sobre alertas ==== +<note important> 
- +**Atenção**\\ 
-No __ed__, há uma diferença sutil entre erros e alertas. Os alertas são emitidos quando você pode perder dados do //buffer// por fechar o editor ou carregar algum outro arquivo. Como mostrei no exemplo anterior, se você insistir em uma ação desse tipo, o __ed__ entenderá que você sabe o que está fazendo e não entrará no seu caminho. +\\ 
- +No __ed__, há uma diferença sutil entre erros e alertas. Os alertas são emitidos quando você pode perder dados do //buffer// por fechar o editor ou carregar algum outro arquivo. Como mostrei no exemplo anterior, se você insistir em uma ação desse tipo, o __ed__ entenderá que você sabe o que está fazendo e não entrará no seu caminho.\\ 
-Mas há uma detalhe que pode te pegar de surpresa: depois que o __ed__ emite o alerta de que o //buffer// foi alterado, ele considera que o alerta já foi dado. Se você continuar a editar o //buffer// depois disso e mais tarde resolver fechar o editor, ele não emitirá outro alerta e encerrará. +\\ 
 +Mas há uma detalhe que pode te pegar de surpresa: depois que o __ed__ emite o alerta de que o //buffer// foi alterado, ele considera que o alerta já foi dado. Se você continuar a editar o //buffer// depois disso e mais tarde resolver fechar o editor, ele não emitirá outro alerta e encerrará.\\ 
 +\\
 Portanto, é uma boa prática salvar as modificações feitas logo depois do alerta, caso realmente queira salvar. Mais à frente veremos como modificar um arquivo e como salvar modificações. Quando você salva o conteúdo do //buffer// o __ed__ volta a considerar que precisa te alertar, se houver mais modificações e você tentar executar outra ação que possa ocasionar perda. Portanto, é uma boa prática salvar as modificações feitas logo depois do alerta, caso realmente queira salvar. Mais à frente veremos como modificar um arquivo e como salvar modificações. Quando você salva o conteúdo do //buffer// o __ed__ volta a considerar que precisa te alertar, se houver mais modificações e você tentar executar outra ação que possa ocasionar perda.
 +</note>
 ===== Indo e voltando ===== ===== Indo e voltando =====
  
Linha 719: Linha 721:
 ===== Mais comandos de visualização ===== ===== Mais comandos de visualização =====
  
-Até aqui você só utilizou o comando ''p'' para ver o conteúdo das linhas (seja explicitamente, ou implicitamente, apenas fornecendo um endereço para navegar). Além dele, existem outros dois comandos que também servem para mostrar o conteúdo das linhas, mas de outras formas.+Até aqui você só utilizou o comando **p** para ver o conteúdo das linhas (seja explicitamente, ou implicitamente, apenas fornecendo um endereço para navegar). Além dele, existem outros dois comandos que também servem para mostrar o conteúdo das linhas, mas de outras formas.
  
-O primeiro deles é o comando ''n'', que mostra o conteúdo da linha (igual ''p''), mas precedido pelo número da linha.+O primeiro deles é o comando **n**, que mostra o conteúdo da linha (igual **p**), mas precedido pelo número da linha.
  
 <code> <code>
Linha 742: Linha 744:
 </code> </code>
  
-Como você pode imaginar, esse é um recurso valioso para edição de programas e arquivos de configuração. E ele também é útil para se localizar em um arquivo. Antes falamos do comando ''='' que pode ser usado para isso. Mas talvez digitar ''.='' seja menos prático do que apenas ''n'', que ainda tem o benefício de mostrar o conteúdo da linha atual.+Como você pode imaginar, esse é um recurso valioso para edição de programas e arquivos de configuração. E ele também é útil para se localizar em um arquivo. Antes falamos do comando **=** que pode ser usado para isso. Mas talvez digitar **.=** seja menos prático do que apenas **n**, que ainda tem o benefício de mostrar o conteúdo da linha atual.
  
-Agora vamos ver o outro comando, ''l''. Ele mostra o conteúdo das linhas de forma inequívoca.+Agora vamos ver o outro comando, **l** (letra //éle//). Ele mostra o conteúdo das linhas de forma inequívoca.
  
 O que quer dizer "inequívoca" nesse caso? Quer dizer que todos os caracteres estarão visíveis e você saberá exatamente quais são, sejam eles imprimíveis (como letras, números, pontuações, etc) ou não (caracteres de controle, espaços, tabulações, fim de linha, etc). Vejamos na prática: O que quer dizer "inequívoca" nesse caso? Quer dizer que todos os caracteres estarão visíveis e você saberá exatamente quais são, sejam eles imprimíveis (como letras, números, pontuações, etc) ou não (caracteres de controle, espaços, tabulações, fim de linha, etc). Vejamos na prática:
Linha 757: Linha 759:
 </code> </code>
  
-Percebeu a diferença? No lugar de uma apresentação bonitinha, temos uma outra mais feia, mas também mais reveladora. Primeiro, para cada fim de linha temos um sinal de cifrão (''$'') para deixar evidente que ali há um caractere de fim de linha, que é um caractere não imprimível (também muitas vezes expresso como ''\n'' em algumas representações).+Percebeu a diferença? No lugar de uma apresentação bonitinha, temos uma outra mais feia, mas também mais reveladora. Primeiro, para cada fim de linha temos um sinal de cifrão (**$**) para deixar evidente que ali há um caractere de fim de linha, que é um caractere não imprimível (também muitas vezes expresso como **\n** em algumas representações).
  
-Caracteres do conjunto ASCII são apresentados sem nenhuma alteração, mas caracteres fora desse conjunto (como letras com til, acentos, cedilha) e também os caracteres de controle são apresentados na notação ''\ddd'' (onde cada ''d'' é um dígito octal). Portanto, podemos saber cada um dos bytes que está impresso no //buffer// pela sua representação octal, caso não seja imprimível ou não seja ASCII.+Caracteres imprimíveis do conjunto ASCII são apresentados sem nenhuma alteração, mas caracteres fora desse conjunto (como letras com til, acentos, cedilha) e também os caracteres de controle são apresentados na notação **\ddd** (onde cada //d// é um dígito octal).
  
-para quê isso é útil? As funções disso variam bastante. Por exemplovocê deve se lembrar quando citei nas desvantagens do ed a possibilidade de acidentalmente incluir caracteres de controle. Pois bemse você usar o comando ''p'' para mostrar uma linha, esses caracteres ficam ocultos.+Portanto, podemos saber cada um dos bytes que está impresso no //buffer// pela sua representação octal, caso não seja imprimível ou não seja ASCII. aindatabulações são representadas pela sequência de caracteres **\t**, para que possam ser distinguidas de espaços.
  
-Porémcom o comando ''l'' você verá que esses caracteres estão alie saberá que precisa fazer uma correção. Como? Existem formas diferentes. Por enquanto você pode usar um comando que já aprendeu, o comando ''c'', que substitui o conteúdo de uma linha por uma ou mais outras linhas. Essa normalmente não é a forma mais confortável de fazer essa correçãoe mais adiante nesse tutorial vamos ver outra maneira mais conveniente.+E para quê isso é útil? As funções disso variam bastante. Por exemplo, você deve se lembrar quando citei nas desvantagens do __ed__ a possibilidade de acidentalmente incluir caracteres de controle. Pois bemse você usar o comando **p** para mostrar uma linha, esses caracteres ficam ocultos.
  
-Mas o comando ''l'' não serve só para isso. Como eu disse também, nas vantagens do ed, esse editor é resistente a conteúdo binário. Ou seja, você pode abrir arquivos binários nele (como um arquivo de imagem, por exemplo), que ele não vai reclamar. E pode mostrar todo o conteúdo do arquivo usando o comando ''l''. Isso é conveniente pois assim você não polui a tela com caracteres "estranhos" como tipicamente ocorre ao tentar mostrar conteúdo binário na tela do terminal.+Porém, com o comando **l** você verá que esses caracteres estão ali, e saberá que precisa fazer uma correção. Como? Existem formas diferentes. Por enquanto você pode usar um comando que já aprendeu, o comando **c**, que substitui o conteúdo de uma linha por uma ou mais outras linhas. Essa normalmente não é a forma mais confortável de fazer essa correção, e mais adiante nesse tutorial vamos ver outra maneira mais conveniente. 
 + 
 +Mas o comando **l** não serve só para isso. Como eu disse também, nas vantagens do __ed__, esse editor é resistente a conteúdo binário. Ou seja, você pode abrir arquivos binários nele (como um arquivo de imagem, por exemplo), que ele não vai reclamar. E pode mostrar todo o conteúdo do arquivo usando o comando **l**. Isso é conveniente pois assim você não polui a tela com caracteres "estranhos" como tipicamente ocorre ao tentar mostrar conteúdo binário na tela do terminal.
  
 Ao editar arquivos gravados em codificações diferentes (por exemplo, em ISO-8859-1 em um sistema que espera UTF-8), esse comando também poderá ser útil, pois mostrar caracteres de uma codificação diferente do esperado também pode resultar em caracteres não imprimíveis ou símbolos inesperados aparecendo na tela. Ao editar arquivos gravados em codificações diferentes (por exemplo, em ISO-8859-1 em um sistema que espera UTF-8), esse comando também poderá ser útil, pois mostrar caracteres de uma codificação diferente do esperado também pode resultar em caracteres não imprimíveis ou símbolos inesperados aparecendo na tela.
  
-E ainda, você pode eventualmente trabalhar com arquivos que sejam majoritariamente textuais, mas que tenham dentro deles partes compostas por arquivos binários. Isso acontece por exemplo em arquivos no formato SVG com imagens rasterizadas embutidas, ocorre às vezes em programas Shell com programas binários no final.+E ainda, você pode eventualmente trabalhar com arquivos que sejam majoritariamente textuais, mas que tenham dentro deles partes compostas por arquivos binários. Isso acontece por exemplo em arquivos no formato SVG com imagens rasterizadas embutidas, ocorre às vezes em programas escritos em Shell com programas binários no final.
  
-Portanto, o ed pode ser muito útil como uma ferramenta de inspeção de arquivos.+Portanto, o __ed__ pode ser muito útil como uma ferramenta de inspeção de arquivos.
  
-Ainda outra situação onde esse comando vem a calhar é quando você quer saber se existem espaços no final da linha. O comando ''p'' não mostra isso, mas com o comando ''l'' você consegue saber, pois vão aparecer os espaços antes do cifrão (que representa o final da linha).+Ainda outra situação onde esse comando vem a calhar é quando você quer saber se existem espaços no final da linha. O comando **p** não mostra isso, mas com o comando **l** você consegue saber, pois vão aparecer os espaços antes do cifrão (que representa o final da linha).
  
-Um ponto importante a saber sobre os comandos de apresentação (''p''''n'' ''l'') é que eles podem ser combinados com vários dos outros comandos do ed (e inclusive entre eles mesmos).+Um ponto importante a saber sobre os comandos de apresentação (**p****n** **l**) é que eles podem ser combinados com vários dos outros comandos do __ed__ (e inclusive entre eles mesmos).
  
 <code> <code>
Linha 787: Linha 791:
 </code> </code>
  
-Nesse exemplo, ao usar ''n'' ''l'' de uma só vez, vemos as linhas numeradas e em apresentação inequívoca.+Nesse exemplo, ao usar **n** **l** de uma só vez, vemos as linhas numeradas e em apresentação inequívoca.
  
 Veremos depois que anexar comandos de apresentação a outro comando é útil em operações de pesquisa e substituição de texto, para mostrar uma linha pesquisada ou o resultado de alguma alteração aplicada. Veremos depois que anexar comandos de apresentação a outro comando é útil em operações de pesquisa e substituição de texto, para mostrar uma linha pesquisada ou o resultado de alguma alteração aplicada.
 +
 ===== Pesquisa de texto ===== ===== Pesquisa de texto =====
  
Linha 897: Linha 902:
 ===== Expressões regulares ===== ===== Expressões regulares =====
  
-Talvez esse último exemplo que mostrei, do corpo da função tenha te deixado com a pulga atrás da orelha, e se perguntando algo como "mas e se existisse outro fecha-chaves dentro da função, para um bloco ''if'' por exemplo?"+Talvez esse último exemplo que mostrei, do corpo da função tenha te deixado com a pulga atrás da orelha, e se perguntando algo como "mas e se existisse outro fecha-chaves dentro da função, para um bloco **if** por exemplo?"
  
 Isso realmente comprometeria nosso exemplo, pois a pesquisa ia parar nele, e não veríamos o restante da função. É aí que entra a nossa capacidade de definir algumas regras dentro da pesquisa, para garantir que vamos encontrar exatamente aquilo que queremos. Pesquisar apenas um fecha-chaves pode retornar qualquer um, mas eu poderia determinar que quero especificamente o fecha-chaves que está isolado na linha, ou seja, início da linha, seguido do fecha-chaves, seguido do fim da linha. Isso realmente comprometeria nosso exemplo, pois a pesquisa ia parar nele, e não veríamos o restante da função. É aí que entra a nossa capacidade de definir algumas regras dentro da pesquisa, para garantir que vamos encontrar exatamente aquilo que queremos. Pesquisar apenas um fecha-chaves pode retornar qualquer um, mas eu poderia determinar que quero especificamente o fecha-chaves que está isolado na linha, ou seja, início da linha, seguido do fecha-chaves, seguido do fim da linha.
Linha 909: Linha 914:
 </code> </code>
  
-Mas o que foi isso? Se você já usou expressões regulares, sabe que os caracteres ''^'' ''$'' funcionam como âncoras, respectivamente para o início e para o fim da linha.+Mas o que foi isso? Se você já usou expressões regulares, sabe que os caracteres **^** **$** funcionam como âncoras, respectivamente para o início e para o fim da linha.
  
-Não está no escopo desse tutorial ensinar a usar expressões regulares, mas atente-se aos exemplos, pois eles serão comentados (e depois busque entender como funcionam as [[https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap09.html#tag_09_03|expressões regulares básicas do padrão POSIX]], que são usadas no ed).+Não está no escopo desse tutorial ensinar a usar expressões regulares, mas atente-se aos exemplos, pois eles serão comentados (e depois busque entender como funcionam as [[prog:regex|expressões regulares]], especialmente as BREs (do padrão POSIX), que são usadas no __ed__.
  
 Do mesmo modo que essas expressões podem restringir o escopo da nossa pesquisa, também podem ampliar. Podemos fazer mais do que buscas literais, pesquisando por classes de caracteres (letras maiúsculas, minúsculas, dígitos numéricos decimais ou hexadecimais, caracteres de pontuação, etc.) ou combinações dessas classes, de modo que uma mesma pesquisa pode servir para encontrar vários termos diferentes, mas que se encaixam nas regras definidas. Do mesmo modo que essas expressões podem restringir o escopo da nossa pesquisa, também podem ampliar. Podemos fazer mais do que buscas literais, pesquisando por classes de caracteres (letras maiúsculas, minúsculas, dígitos numéricos decimais ou hexadecimais, caracteres de pontuação, etc.) ou combinações dessas classes, de modo que uma mesma pesquisa pode servir para encontrar vários termos diferentes, mas que se encaixam nas regras definidas.
  
-Vejamos um exemplo simples: se eu quiser buscar quaisquer diretivas de pré-processamento do código em ''area.c'' (portanto, as linhas iniciadas em ''#''), eu poderia fazer a seguinte pesquisa:+Vejamos um exemplo simples: se eu quiser buscar quaisquer diretivas de pré-processamento do código em //area.c// (portanto, as linhas iniciadas em **#**), eu poderia fazer a seguinte pesquisa:
  
 <code> <code>
Linha 925: Linha 930:
 </code> </code>
  
-Note que aqui pesquisei por qualquer linha que tenha o caractere ''#'' logo no início, seguido de ''.*'' que significa qualquer quantidade (''*'') de qualquer coisa (''.''). Talvez "qualquer coisa" seja um critério muito abrangente. Poderíamos, por exemplo, determinar que o caractere de cerquilha (''#'') seja seguido de caracteres alfabéticos (usando a classe ''alpha'' do POSIX).+Note que aqui pesquisei por qualquer linha que tenha o caractere **#** logo no início, seguido de **.*** que significa qualquer quantidade (*****) de qualquer coisa (**.**). Talvez "qualquer coisa" seja um critério muito abrangente. Poderíamos, por exemplo, determinar que o caractere de cerquilha (**#**) seja seguido de caracteres alfabéticos (usando a classe **alpha** do POSIX).
  
 <code> <code>
Linha 944: Linha 949:
 </code> </code>
  
-Se estivéssemos usando as expressões regulares estendidas, poderíamos usar um ''+'' no lugar do ''*''. Mas isso não existe nas expressões regulares básicas, então o equivalente seria esse ''\{1,\}'', que quer dizer, "ao menos um". Os caracteres de abrir e fechar chaves nesse caso precisam ser "escapados" (com a barra invertida, ''\''), pois do contrário seriam interpretados literalmente (como inclusive já vimos no tópico anterior).+Se estivéssemos usando as expressões regulares estendidas, poderíamos usar um **+** no lugar do *****. Mas isso não existe nas expressões regulares básicas, então o equivalente seria esse **\{1,\}**, que quer dizer, "ao menos um". Os caracteres de abrir e fechar chaves nesse caso precisam ser "escapados" (com a barra invertida, **\**), pois do contrário seriam interpretados literalmente (como inclusive já vimos no tópico anterior).
  
 Eu friso essas diferenças das expressões básicas pois mesmo pessoas que já estão acostumadas a usar expressões regulares com frequência se confundem ao usar esse "dialeto", que é bem menos comum de ser usado. Eu friso essas diferenças das expressões básicas pois mesmo pessoas que já estão acostumadas a usar expressões regulares com frequência se confundem ao usar esse "dialeto", que é bem menos comum de ser usado.
  
-Antes que me esqueça de dizer, agora você tem mais um recurso para lidar com os caracteres de controle acidentais: existe a classe ''cntrl'' do POSIX, que abrange caracteres desse tipo, e você pode pesquisar por eles para identificar linhas que precisam de correção. Isso será ainda mais útil quando você aprender a usar o comando de substituição de texto, logo mais.+Antes que me esqueça de dizer, agora você tem mais um recurso para lidar com os caracteres de controle acidentais: existe a classe **cntrl** do POSIX, que abrange caracteres desse tipo, e você pode pesquisar por eles para identificar linhas que precisam de correção. Isso será ainda mais útil quando você aprender a usar o comando de substituição de texto, logo mais. 
 + 
 +<note important> 
 +Tenha em mente que a classe **cntrl** abrange caracteres de tabulação, os quais você pode querer manter. Portanto, pesquisar por caracteres nessa classe em um arquivo que possui tabulações pode resultar em alguns falsos positivos. 
 +</note>
  
 De modo geral, expressões regulares são um recurso muito poderoso, mas não tenha pressa em tirar o máximo disso, pois usar expressões equivocadas muitas vezes tende a irritar. Comece usando aquilo que tem mais certeza de que vai funcionar, e conforme se familiarizar, você pode recorrer a expressões mais complexas. De modo geral, expressões regulares são um recurso muito poderoso, mas não tenha pressa em tirar o máximo disso, pois usar expressões equivocadas muitas vezes tende a irritar. Comece usando aquilo que tem mais certeza de que vai funcionar, e conforme se familiarizar, você pode recorrer a expressões mais complexas.
  
-No ed, as expressões regulares são usadas não apenas em pesquisas comuns, como vimos até aqui, mas também em algumas outras ocasiões, como comandos de substituição de texto e comandos globais.+No __ed__, as expressões regulares são usadas não apenas em pesquisas comuns, como vimos até aqui, mas também em algumas outras ocasiões, como comandos de substituição de texto e comandos globais.
  
 ===== Substituindo texto ===== ===== Substituindo texto =====
  
-Vamos voltar a falar sobre comandos que alteram o conteúdo do //buffer//. Já tínhamos visto o comando ''c'', que altera todo o conteúdo da linha (ou das linhas) pelo texto fornecido. Isso resolve muita coisa, mas às vezes pode ser pouco prático. Em alguns casos, você só quer substituir alguns caracteres dentro de uma linha, um ajuste mais pontual.+Vamos voltar a falar sobre comandos que alteram o conteúdo do //buffer//. Já tínhamos visto o comando **c**, que altera todo o conteúdo da linha (ou das linhas) pelo texto fornecido. Isso resolve muita coisa, mas às vezes pode ser pouco prático. Em alguns casos, você só quer substituir alguns caracteres dentro de uma linha, um ajuste mais pontual.
  
-Nesse caso, usamos o comando ''s'', que opera "dentro" das linhas. No ed, ao contrário de editores de texto visuais, não existe a noção de posição do cursor dentro de uma linha. Não avançamos ou retrocedemos entre caracteres de uma linha, pois a noção de posição está restrita a linhas.+Nesse caso, usamos o comando **s**, que opera "dentro" das linhas. No __ed__, ao contrário de editores de texto visuais, não existe a noção de posição do cursor dentro de uma linha. Não avançamos ou retrocedemos entre caracteres de uma linha, pois a noção de posição está restrita a linhas.
  
-Porém, com o auxílio de expressões regulares, podemos determinar qual (ou quais) caracteres serão editados dentro da linha. Podemos usar uma expressão que abrange toda a linha também (''^.*$''), mas nesse caso faria mais sentido usar o comando ''c'', provavelmente.+Porém, com o auxílio de expressões regulares, podemos determinar qual (ou quais) caracteres serão editados dentro da linha. Podemos usar uma expressão que abrange toda a linha também (**^.*$**), mas nesse caso faria mais sentido usar o comando **c**, provavelmente.
  
-A estrutura do comando ''s'' é um pouco diferente dos comandos que vimos até aqui. Nele, informamos primeiro um termo a ser pesquisado dentro da linha, depois o termo que o substituirá (podendo ser vazio), e ao fim podemos anexar um comando de visualização (''p''''l'' ou ''n''), para ver o resultado da substituição.+A estrutura do comando **s** é um pouco diferente dos comandos que vimos até aqui. Nele, informamos primeiro um termo a ser pesquisado dentro da linha, depois o termo que o substituirá (podendo ser vazio), e ao fim podemos anexar um comando de visualização (**p****l** ou **n**), para ver o resultado da substituição.
  
 Esses três argumentos (termo pesquisado, texto substituto e comando de visualização) são geralmente separados por barras. Então temos a seguinte estrutura: Esses três argumentos (termo pesquisado, texto substituto e comando de visualização) são geralmente separados por barras. Então temos a seguinte estrutura:
Linha 970: Linha 979:
 </code> </code>
  
-O comando ''s'' é muito versátil. Ele pode ser usado tanto para adicionar conteúdo novo (sem remover nada), substituir algo, ou apenas remover uma parte da linha (sem adicionar nada no lugar). Vejamos um exemplo de remoção. Se reparar no programa ''area.c'' (e tiver conhecimento de C), há uma linha com um erro lógico, a linha 22. Nela, temos uma função ''printf'' com um argumento sobrando (''raio''). Vamos tratar de arrumar isso.+O comando **s** é muito versátil. Ele pode ser usado tanto para adicionar conteúdo novo (sem remover nada), substituir algo, ou apenas remover uma parte da linha (sem adicionar nada no lugar). Vejamos um exemplo de remoção. Se reparar no programa //area.c// (e tiver conhecimento de C), há uma linha com um erro lógico, a linha 22. Nela, temos uma função **printf** com um argumento sobrando (//raio//). Vamos tratar de arrumar isso.
  
 <code> <code>
Linha 979: Linha 988:
 </code> </code>
  
-O que aconteceu aqui? Na linha 22, usei o comando ''s'' para procurar pelo termo "raio, " (note o espaço ao fim), e substituí-lo por nada (daí o motivo de haver duas barras consecutivas), e por fim uso o comando ''p'' para mostrar o resultado da substituição.+O que aconteceu aqui? Na linha 22, usei o comando **s** para procurar pelo termo "raio, " (note o espaço ao fim), e substituí-lo por nada (daí o motivo de haver duas barras consecutivas), e por fim uso o comando **p** para mostrar o resultado da substituição.
  
-E se eu quiser substituir várias linhas de uma vez só, é possível? Sim. Por exemplo, talvez eu pense que o nome da função ''area_do_circulo'' é mais longa do que o necessário e queira trocar todas as suas ocorrências por ''area_circulo''. Simples:+E se eu quiser substituir várias linhas de uma vez só, é possível? Sim. Por exemplo, talvez eu pense que o nome da função //area_do_circulo// é mais longa do que o necessário e queira trocar todas as suas ocorrências por //area_circulo//. Simples:
  
 <code> <code>
Linha 989: Linha 998:
 </code> </code>
  
-"Mas pode isso?" Claro que pode. As linhas que não possuem o termo ''area_do_circulo'' apenas ignoram a instrução, enquanto as que possuem fazem a alteração instruída. Note que eu omiti o comando de visualização, e ao omitir também a barra que antecede o comando, o ed entende que deve executar a ação padrão (''p''), porém apenas a última linha alterada é exibida.+"Mas pode isso?" Claro que pode. As linhas que não possuem o termo ''area_do_circulo'' apenas ignoram a instrução, enquanto as que possuem fazem a alteração instruída. Note que eu omiti o comando de visualização, e ao omitir também a barra que antecede o comando, o __ed__ entende que deve executar a ação padrão (**p**), porém apenas a última linha alterada é exibida.
  
-Lembrando mais uma vez, a vírgula que antecede o comando, na prática equivale a ''1,$''. Eu poderia definir qualquer intervalo de linhas para passar por esse processo, não necessariamente o //buffer// inteiro.+Lembrando mais uma vez, a vírgula que antecede o comando, na prática equivale a **1,$**. Eu poderia definir qualquer intervalo de linhas para passar por esse processo, não necessariamente o //buffer// inteiro.
  
 Enfim, vamos salvar o arquivo com as modificações que fizemos até aqui. Enfim, vamos salvar o arquivo com as modificações que fizemos até aqui.
Linha 1004: Linha 1013:
 Se eu quisesse mostrar a alteração de cada uma das linhas, seria possível também, mas para isso teria que usar um comando global, assunto que ainda vamos explorar. Se eu quisesse mostrar a alteração de cada uma das linhas, seria possível também, mas para isso teria que usar um comando global, assunto que ainda vamos explorar.
  
-O comando ''s'' é seu principal aliado no momento de remover os caracteres de controle inseridos acidentalmente:+O comando **s** é um grande aliado no momento de remover os caracteres de controle inseridos acidentalmente:
  
 <code> <code>
Linha 1024: Linha 1033:
 </code> </code>
  
-No comando de substituição demonstrado acima, removemos quais quer ocorrências de quaisquer caracteres de controle (classe ''cntrl''), em qualquer quantidade, e ao fim do comando usamos o sufixo ''g'', que significa que a substituição será refeita para toda ocorrência dentro da linha (do contrário, a substituição se limitaria à primeira ocorrência de cada linha).+No comando de substituição demonstrado acima, removemos quaisquer ocorrências de quaisquer caracteres de controle (classe **cntrl**), em qualquer quantidade, e ao fim do comando usamos o sufixo **g**, que significa que a substituição será refeita para toda ocorrência dentro da linha (do contrário, a substituição se limitaria à primeira ocorrência de cada linha). 
 + 
 +<note warning> 
 +**Cuidado!**\\ 
 +\\ 
 +Como alertei antes, caracteres de tabulação se enquadram na classe **cntrl**, portanto evite fazer esse tipo de substituição irrestrita quando houver tabulações que queira preservar.\\ 
 +\\ 
 +Nestes casos será mais interessante fazer substituições pontuais. Comandos globais interativos (explicado mais adiante) também podem ajudar nesses casos. 
 +</note>
  
-Note que após a substituição, os caracteres de controle não aparecem nem mesmo após exibir a linha de modo inequívoco, com '',l''.+Note no exemplo acima que após a substituição, os caracteres de controle não aparecem nem mesmo após exibir a linha de modo inequívoco, com **,l**.
  
 Do mesmo modo, o comando de substituição pode servir para eliminar os espaços sobrando no fim da linha: Do mesmo modo, o comando de substituição pode servir para eliminar os espaços sobrando no fim da linha:
Linha 1053: Linha 1070:
 </code> </code>
  
-Agora, usamos a classe ''blank'' para remover quaisquer espaços vazios em qualquer quantidade, que antecedam o fim da linha. Nesse caso não é necessário usar o sufixo ''g'', pois a pesquisa está ancorada no fim da linha (''$''), isto é, só há um fim de linha por linha. E nesse caso é importante que haja essa âncora, pois do contrário removeria todos os espaços no arquivo, independente da posição.+Agora, usamos a classe **blank** para remover quaisquer espaços vazios em qualquer quantidade, que antecedam o fim da linha. Nesse caso não é necessário usar o sufixo **g**, pois a pesquisa está ancorada no fim da linha (**$**), isto é, só há um fim de linha por linha. E nesse caso é importante que haja essa âncora, pois do contrário removeria todos os espaços no arquivo, independente da posição.
  
-No lugar do sufixo ''g'', podemos usar também um número inteiro, caso quiséssemos substituir a //n-ésima// ocorrência (caso haja; se não houver, um erro é retornado), onde N é o número informado.+No lugar do sufixo **g**, podemos usar também um número inteiro, caso quiséssemos substituir a //n-ésima// ocorrência (caso haja; se não houver, um erro é retornado), onde N é o número informado.
  
 <code> <code>
Linha 1069: Linha 1086:
 </code> </code>
  
-Ainda sobre substituições, lembra-se quando eu disse que a estrutura do comando ''s'' //geralmente// é separada por barras? Pois então, geralmente mas nem sempre. Se você precisar substituir algum texto que possua barras dentro dele, talvez fique desconfortável ou confuso.+Ainda sobre substituições, lembra-se quando eu disse que a estrutura do comando **s** //geralmente// é separada por barras? Pois então, geralmente mas nem sempre. Se você precisar substituir algum texto que possua barras dentro dele, talvez fique desconfortável ou confuso.
  
 Imagine, por exemplo, substituir um texto que representa caminhos em um sistema de arquivos (sendo que no UNIX os diretórios são separados por barras). Facilmente você se confundiria, ou na melhor das hipóteses, teria que adicionar uma barra invertida para cada uma das barras do texto, para que sejam tratadas literalmente. Imagine, por exemplo, substituir um texto que representa caminhos em um sistema de arquivos (sendo que no UNIX os diretórios são separados por barras). Facilmente você se confundiria, ou na melhor das hipóteses, teria que adicionar uma barra invertida para cada uma das barras do texto, para que sejam tratadas literalmente.
  
-Por isso, podemos usar outros caracteres no lugar da barra. Por exemplo, você pode preferir, em alguns casos, usar o caractere //pipe// (''|''), ou talvez um ponto de exclamação (''!'').+Por isso, podemos usar outros caracteres no lugar da barra. Por exemplo, você pode preferir, em alguns casos, usar o caractere //pipe// (**|**), ou talvez um ponto de exclamação (**!**).
  
 Exemplo: Exemplo:
Linha 1117: Linha 1134:
 Há um limite, porém. Só podemos usar até 9 capturas dessa forma. Não que seja muito confortável abusar desse recurso. Há um limite, porém. Só podemos usar até 9 capturas dessa forma. Não que seja muito confortável abusar desse recurso.
  
-Se no lugar de capturar apenas parte da pesquisa, quiser capturar a pesquisa inteira para reutilizar no texto de substituição, não precisa usar um grupo, pois existe um atalho para essa captura, usando "e comercial" (''&'').+Se no lugar de capturar apenas parte da pesquisa, quiser capturar a pesquisa inteira para reutilizar no texto de substituição, não precisa usar um grupo, pois existe um atalho para essa captura, usando "e comercial" (**&**).
  
 <code> <code>
Linha 1134: Linha 1151:
 ==== Reutilizando pesquisas e substituições ==== ==== Reutilizando pesquisas e substituições ====
  
-Do mesmo modo que usar o endereçamento de pesquisa (''/'') sem informar o termo pesquisado repete a última pesquisa, podemos também reutilizar a última pesquisa feita dentro de um comando de substituição e novos comandos de substituição (ou novas pesquisas também). O que ocorre é que independente de onde você fizer a pesquisa, ela fica salva para reuso posterior.+Do mesmo modo que usar o endereçamento de pesquisa (**/**) sem informar o termo pesquisado repete a última pesquisa, podemos também reutilizar a última pesquisa feita dentro de um comando de substituição e novos comandos de substituição (ou novas pesquisas também). O que ocorre é que independente de onde você fizer a pesquisa, ela fica salva para reuso posterior.
  
 <code> <code>
Linha 1149: Linha 1166:
 </code> </code>
  
-Além da pesquisa, podemos reaproveitar também o último termo substituto utilizado. Para isso, basta usar um sinal de porcentagem (''%'') como termo substituto.+Além da pesquisa, podemos reaproveitar também o último termo substituto utilizado. Para isso, basta usar um sinal de porcentagem (**%**) como termo substituto.
  
  
Linha 1163: Linha 1180:
 Veja que nesse caso reaproveitei as duas coisas: a pesquisa e a substituição. Veja que nesse caso reaproveitei as duas coisas: a pesquisa e a substituição.
  
-Outro ponto importante a destacar sobre o reaproveitamento de pesquisas é que se a pesquisa utilizava grupos de captura (expressões entre ''\('' ''\)''), então as referência a esses grupos também podem ser reaproveitadas na substituição.+Outro ponto importante a destacar sobre o reaproveitamento de pesquisas é que se a pesquisa utilizava grupos de captura (expressões entre **\(** **\)**), então as referência a esses grupos também podem ser reaproveitadas na substituição.
 ===== Desfazendo e refazendo ===== ===== Desfazendo e refazendo =====
  
 Vez ou outra, você pode executar alguma alteração no //buffer// e logo em seguida perceber que não era aquilo que queria. Isso é especialmente comum em comandos de substituição. Basta uma expressão regular mal formulada para substituir o trecho errado, por exemplo. Vez ou outra, você pode executar alguma alteração no //buffer// e logo em seguida perceber que não era aquilo que queria. Isso é especialmente comum em comandos de substituição. Basta uma expressão regular mal formulada para substituir o trecho errado, por exemplo.
  
-Por esse motivo, existe um comando que desfaz a última alteração, o comando ''u''. É sempre bom, depois de aplicar alguma alteração no //buffer// conferir se o resultado é mesmo o esperado. Lembra-se quando falei que você pode anexar comandos de visualização a vários outros comandos? Pois então, para essa finalidade isso é bem útil (especialmente em comandos de substituição).+Por esse motivo, existe um comando que desfaz a última alteração, o comando **u**. É sempre bom, depois de aplicar alguma alteração no //buffer// conferir se o resultado é mesmo o esperado. Lembra-se quando falei que você pode anexar comandos de visualização a vários outros comandos? Pois então, para essa finalidade isso é bem útil (especialmente em comandos de substituição).
  
-O comando ''u'' tem uma particularidade: se você executá-lo de novo (sem ter feito alguma outra alteração no //buffer//), ele refaz a alteração desfeita.+O comando **u** tem uma particularidade: se você executá-lo de novo (sem ter feito alguma outra alteração no //buffer//), ele refaz a alteração desfeita.
  
 <code> <code>
Linha 1186: Linha 1203:
 </code> </code>
  
-Perceba que o comando ''p'' foi usado como sufixo em ''u'' nesse caso, para desfazer e já mostrar o resultado (e depois para refazer e mostrar o resultado).+Perceba que o comando **p** foi usado como sufixo em **u** nesse caso, para desfazer e já mostrar o resultado (e depois para refazer e mostrar o resultado).
  
-Essa forma de funcionar do comando ''u'' pode surpreender usuários acostumados com editores que desfazem várias ações em sequência. No ed, apenas a última alteração pode ser desfeita. Portanto, é bom ter cuidado com as alterações que aplica, salvar o arquivo de tempos em tempos, após alterações importantes, e a depender da criticidade do arquivo, possuir backups.+Essa forma de funcionar do comando **u** pode surpreender usuários acostumados com editores que desfazem várias ações em sequência. No __ed__, apenas a última alteração pode ser desfeita. Portanto, é bom ter cuidado com as alterações que aplica, salvar o arquivo de tempos em tempos, após alterações importantes, e a depender da criticidade do arquivo, possuir //backups//.
  
-Recapitulando, se você fez várias alterações em um //buffer// (carregado a partir de um arquivo), e de repente decide que quer desfazer todas elas, isso é possível. Basta usar o comando ''E'', que recarrega o arquivo no estado inicial. Vejamos um exemplo:+Recapitulando, se você fez várias alterações em um //buffer// (carregado a partir de um arquivo), e de repente decide que quer desfazer todas elas, isso é possível. Basta usar o comando **E**, que recarrega o arquivo no estado inicial. Vejamos um exemplo:
  
 <code> <code>
Linha 1212: Linha 1229:
 </code> </code>
  
-Isso será útil, se você de tempos em tempos salvar as modificações que for fazendo. Dessa forma, poderá sempre retornar ao estado do último salvamento. Mas tenha em mente que usar o comando ''E'' para desfazer tudo não permitirá refazer as alterações depois (como ocorre com ''u'' para uma única alteração).+Isso será útil, se você de tempos em tempos salvar as modificações que for fazendo. Dessa forma, poderá sempre retornar ao estado do último salvamento. Mas tenha em mente que usar o comando **E** para desfazer tudo não permitirá refazer as alterações depois (como ocorre com **u** para uma única alteração).
  
-Se por um lado, você não pode gradualmente desfazer várias alterações, por outro, o comando ''u'' ao menos permite que você compare os resultados antes e depois de aplicar alguma alteração.+Se por um lado, você não pode gradualmente desfazer várias alterações, por outro, o comando **u** ao menos permite que você compare os resultados antes e depois de aplicar alguma alteração.
  
 ===== Deletando ===== ===== Deletando =====
Linha 1864: Linha 1881:
 Eu havia comentado brevemente sobre a integração do __ed__ com os comandos do sistema. Vamos detalhar como isso funciona. Sendo o editor padrão do UNIX, seria até estranho que ele não tirasse vantagem dos demais comandos disponíveis no sistema. É parte da filosofia UNIX, afinal. É nessa integração que reside o maior potencial do editor, pois qualquer comando disponível no sistema pode ser utilizado dentro do ed. Eu havia comentado brevemente sobre a integração do __ed__ com os comandos do sistema. Vamos detalhar como isso funciona. Sendo o editor padrão do UNIX, seria até estranho que ele não tirasse vantagem dos demais comandos disponíveis no sistema. É parte da filosofia UNIX, afinal. É nessa integração que reside o maior potencial do editor, pois qualquer comando disponível no sistema pode ser utilizado dentro do ed.
  
-Para executar comandos do sistema no __ed__, usamos o comando ''!''. Por exemplo:+Para executar comandos do sistema no __ed__, usamos o comando **!**. Por exemplo:
  
 <code> <code>
Linha 1882: Linha 1899:
 E você não precisa se restringir apenas aos comandos padrão do sistema. Qualquer comando disponível e que funcionaria normalmente no shell pode ser usado dessa forma. E você não precisa se restringir apenas aos comandos padrão do sistema. Qualquer comando disponível e que funcionaria normalmente no shell pode ser usado dessa forma.
  
-<note> +<note warning
-Não use o comando __cd__ no lançador de comandos do __ed__. Isto não surtirá o efeito que você possivelmente espera. Os comandos são executados em um contexto isolado, então a troca de diretórios ocorreria em uma nova sessão, que encerraria logo em seguida, e para todos os efeitos você continua no mesmo diretório de antes (use o __pwd__ e verá que não houve alteração alguma). Em outras palavras, não há persistência de contexto entre a execução dos comandos do sistema no __ed__.+**Não se iluda!**\\ 
 +\\ 
 +Usar o comando __cd__ no lançador de comandos do __ed__ não surtirá o efeito que você possivelmente espera. Os comandos são executados em um contexto isolado, então a troca de diretórios ocorreria em uma nova sessão, que encerraria logo em seguida, e para todos os efeitos você continua no mesmo diretório de antes.\\ 
 +\\ 
 +Se duvida, compare a saída de __pwd__ antes e depois de executar __cd__ e verá que não houve alteração alguma. Em outras palavras, não há persistência de contexto entre a execução dos comandos do sistema no __ed__.
 </note> </note>
  
-Se quiser repetir o último comando utilizado, basta usar o atalho ''!!'' (duas exclamações).+Se quiser repetir o último comando utilizado, basta usar o atalho **!!** (duas exclamações).
  
 <code> <code>
Linha 1896: Linha 1917:
 </code> </code>
  
-Nesse caso, como houve uma substituição no comando (isto é, do comando fornecido, ''!!'' pelo comando efetivo, ''ls''), ele é exibido logo antes de ser executado, para que você possa ter certeza de qual foi o comando executado.+Nesse caso, como houve uma substituição no comando (isto é, do comando fornecido, **!!** pelo comando efetivo, **ls**), ele é exibido logo antes de ser executado, para que você possa ter certeza de qual foi o comando executado.
  
-Podemos também usar o sinal de percentual (''%'') em comandos como referência ao nome de arquivo memorizado. Isso pode ser útil, por exemplo quando estamos editando um arquivo-fonte e queremos então acionar um compilador ou interpretador para testá-lo logo em seguida. Nesse caso, é necessário salvar o conteúdo do //buffer// antes de acionar o comando.+Podemos também usar o sinal de percentual (**%**) em comandos como referência ao nome de arquivo memorizado. Isso pode ser útil, por exemplo quando estamos editando um arquivo-fonte e queremos então acionar um compilador ou interpretador para testá-lo logo em seguida. Nesse caso, é necessário salvar o conteúdo do //buffer// antes de acionar o comando.
  
 <code> <code>
Linha 1913: Linha 1934:
 </code> </code>
  
-Veja que nesse caso sinal de percentual foi substituído por ''area.c'', e tal como no caso anterior, o comando é exibido logo antes da execução, por ter havido uma substituição, nesse caso, do nome de arquivo. Esse é um programa simples, então apenas compilei e executei. Mas poderia, em um programa mais complexo, acionar o comando __make__ ou qualquer que fosse o comando de construção do programa.+Veja que nesse caso sinal de percentual foi substituído por //area.c//, e tal como no caso anterior, o comando é exibido logo antes da execução, por ter havido uma substituição, nesse caso, do nome de arquivo. Esse é um programa simples, então apenas compilei e executei. Mas poderia, em um programa mais complexo, acionar o comando __make__ ou qualquer que fosse o comando de construção do programa.
  
 Igualmente, poderia estar manipulando o código de um programa interpretado, e então acionar o interpretador para testá-lo. E para além disso, poderia estar manipulando outros tipos de arquivos, como logs, por exemplo, e usando um comando externo como __awk__ ou __sed__ para interpretar o arquivo segundo alguma regra definida. Igualmente, poderia estar manipulando o código de um programa interpretado, e então acionar o interpretador para testá-lo. E para além disso, poderia estar manipulando outros tipos de arquivos, como logs, por exemplo, e usando um comando externo como __awk__ ou __sed__ para interpretar o arquivo segundo alguma regra definida.
utils/ed.1736469761.txt.gz · Última modificação: (edição externa)