====== ed ====== O editor **ed** é o editor de texto original do UNIX. Ele é um editor //de linha de comando//, //interativo//, //minimalista//, //padronizado// e //multimodal//. Vamos detalhar a seguir o que tudo isso significa. * **Linha de comando** Um editor de linha de comando, ao contrário de um editor visual, não exibe o texto sendo editado enquanto ele está sendo editado. Ou seja, ele não é o que classificaríamos como uma ferramenta do tipo "//what you see is what you get//" (WYSIWYG). No lugar disso, o editor nos oferece comandos que podemos usar para instruí-lo a alterar o texto. A princípio, isso pode nos causar uma sensação de afastamento ou cegueira em relação ao texto. Mas não passa de uma questão de costume. Podemos ver o texto editado antes e depois da edição, por meio de comandos que, após algum tempo de uso, tornam-se quase um reflexo natural. E que comandos são esses? Existem vários comandos que podemos usar. //Ir para// uma linha específica é um comando. //Mostrar// o conteúdo da linha selecionada é outro comando. //Substituir// uma parte da linha selecionada por outro texto é outro comando. //Copiar//, //mover//, e //adicionar novas linhas// são ainda outros comandos. E existem mais. Logo mais veremos mais detalhes sobre como operá-los. * **Interatividade** Edição de texto é uma atividade tão corriqueira, que às vezes podemos esquecer as diferentes maneiras como isso pode ser feito. Uma edição pode ocorrer de uma vez só, aplicando uma série de alterações (não-interativo), ou uma alteração de cada vez, fornecida pelo usuário uma por uma. O editor ed, por padrão, é interativo (embora tenha também um modo não-interativo, que veremos depois). Isso significa que fornecemos um comando de cada vez, e então observamos os resultados. Isso nos dá a chance de observar se os resultados foram satisfatórios e quando necessário desfazer a alteração recém-aplicada. * **Minimalismo** O ed não é um editor super sofisticado. Ele provê um conjunto de operações básicas para edição de texto. No entanto, essas operações podem ser combinadas de vários modos (incluindo a interação com comandos do sistema). Em outras palavras, o ed tem tudo que um editor de texto precisa, mas não mais do que isso. * **Padronização** Não apenas o ed é editor original do UNIX, o primeiro editor, mas também ele é "//o editor//" padrão. Aderente ao POSIX ([[https://pubs.opengroup.org/onlinepubs/9799919799/utilities/ed.html|ed - POSIX.1 Rev 2024]]), ele está presente em diferentes sistemas operacionais, sob diferentes implementações. Diferentes, mas compatíveis, justamente por existir essa padronização. O ed é um editor amplamente disponível em sistemas POSIX, portanto é razoável supor que estará instalado e pronto para uso em um sistema UNIX. Isso é conveniente especialmente em ambientes mais restritos, que precisam ter uma instalação mínima e que podem não contar com editores mais sofisticados (e menos econômicos). * **Multimodalismo** Esse talvez seja o conceito que mais confunde novos usuários. Vamos tentar tirar essa barreira do caminho. Modos são estados do editor que determinam qual será o seu comportamento. Para facilitar a compreensão desse conceito, vamos refletir um pouco sobre os editores monomodais, que são mais conhecidos. Em um editor monomodal, as ações do usuário terão sempre os mesmos resultados. Por exemplo, ao digitar caracteres comuns eles serão incorporados ao texto que está sendo editado, e ao usar algum atalho do editor, ele pode disparar alguma ação específica (por exemplo, em muitos editores o atalho ''Ctrl + S'' salva o documento). Ao longo de todo o processo de edição, essas ações sempre terão esses resultados (nesse exemplo, inserir caracteres e salvar o documento). Em um editor multimodal, as ações não serão sempre iguais. Elas dependerão do modo selecionado. O modo determina o que uma ação significa. No editor ed, existem dois modos possíveis: o **modo de entrada**, na qual fornecemos novo texto para o documento, e o **modo de comandos**, no qual fornecemos comandos para alterar o documento. No modo de entrada, quando digitamos "d" em uma linha, estamos apenas fornecendo a letra "d" para o documento, que será incorporada ao texto. Mas no modo de comandos, se informamos a letra "d" em uma linha, estamos acionando o comando de //deleção// (ou remoção), que apaga a linha selecionada. Portanto perceba: um mesmo caractere (d) em um modo é apenas um caractere normal inserido no texto, e no outro é um comando. ===== Historinha ===== Não detalharei muito aqui, mas cabe dizer que o editor ed foi um dos primeiros e mais importantes programas do sistema UNIX. Ele foi originalmente criado por Ken Thompson, posteriormente com contribuições significativas de Dennis Ritchie, ambos conhecidos por uma importante participação autoral no sistema UNIX. Cabe dizer também que a versão em uso hoje na maior parte dos sistemas que o incluem não é a mesma usada naquela época. Mas por ter se tornado parte do padrão POSIX, seu comportamento se manteve consistente entre diferentes implementações. ===== Implementações ===== Existem diferentes implementações do editor ed. Algumas delas são: * [[https://www.gnu.org/software/ed/|GNU]] ([[https://www.gnu.org/software/ed/manual/ed_manual.html|docs]]) * [[https://cgit.freebsd.org/src/tree/bin/ed|FreeBSD]] ([[https://man.freebsd.org/cgi/man.cgi?ed|docs]]) * [[http://cvsweb.netbsd.org/bsdweb.cgi/src/bin/ed/?only_with_tag=MAIN|NetBSD]] ([[https://man.netbsd.org/ed.1|docs]]) * [[https://cvsweb.openbsd.org/src/bin/ed/|OpenBSD]] ([[https://man.openbsd.org/ed|docs]]) ===== Prós e contras ===== Se você sempre usou editores de texto visuais, certamente vai estranhar um editor como o ed, e talvez se pergunte em que situações ou por quais motivos poderia usá-lo. Essa é uma reflexão interessante. As vantagens e desvantagens do ed estão fortemente ligadas às características que citei no início desse documento. ==== Vantagens ==== Vamos começar falando de algumas vantagens: * **Histórico de edições visível** Por ser um editor de linha de comando, todas edições feitas anteriormente ficam visíveis no terminal (mesmo depois que ele é encerrado). Saber o que estava sendo feito há pouco pode ser útil na decisão do que fazer a seguir. Isto vale tanto para a edição do documento quanto para o que possivelmente será feito depois. Por exemplo, você pode editar um script shell e por ter à vista as edições que acabou de fazer, já saber que parâmetros informar ao script no momento de acioná-lo. * **Poucos detalhes a serem memorizados** Por ser um editor minimalista, há pouco que se precise memorizar sobre o seu funcionamento. Ao aprender a usá-lo, você pode precisar consultar a documentação algumas vezes, mas com o tempo você terá tudo que precisa saber na sua cabeça. Daí para a frente, só precisará da sua criatividade para fazer mais com o ed. * **Disponibilidade** Por ser um editor padronizado (e também por ser um editor minimalista) é razoável esperar que ele esteja disponível, mesmo em sistemas com recursos mais limitados. Em alguns casos, ele pode ser a sua única (ou ao menos a única conveniente) forma de editar um arquivo. Mesmo que de um sistema para outro a implementação mude, você provavelmente não precisará se preocupar com isso, pois a padronização garante um comportamento consistente entre implementações diferentes. * **Flexibilidade** Por ser um editor de linha de comando, você pode exibir as linhas na ordem que quiser, pode filtrar apenas um grupo específico de linhas que quer ver, pode redirecionar uma ou mais linhas para um comando e ver a saída do comando, e pode rapidamente avançar e retroceder sobre o texto, sem que para isso todas as linhas entre o ponto A e o ponto B precisem ser exibidas na tela. * **Integração com o sistema** O editor ed pode fazer uso de comandos do sistema. Além da flexibilidade que isso oferece, também é útil para executar determinadas ações diretamente a partir do editor. Como citado no tópico anterior, pode inclusive direcionar todo ou parte do texto editado para algum comando. O contrário também pode ser feito, ou seja, obter a saída de um comando e escrever essa saída no documento sendo editado. Em outras palavras, o editor pode ser minimalista, mas ele tem todo o sistema à disposição para amplificar suas capacidades. * **Dispensa combinações de teclas** Por ser um editor multimodal, não é preciso utilizar combinações de teclas usando ''Ctrl'' e ''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** Por ser um editor minimalista, o ed não possui outras bibliotecas como dependências (nem mesmo //curses// 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 o editor ed fica no diretório ''/bin'' e não em ''/usr/bin''. * **Resistente a arquivos binários** Muitos editores reclamam quando você tenta abrir um arquivo binário neles. Eles só leem arquivos textuais. Mas não o ed. Ele consegue ler arquivos binários também (embora não seja necessariamente a melhor ferramenta para fazer isso). Você pode representar caracteres não textuais em forma octal, o que pode ser útil para inspecionar arquivos binários, ou para ler arquivos textuais que em algumas ocasiões possuem trechos não textuais. * **Zero configuração** Este é um dos pontos que mais me agrada nesse editor. Por ser minimalista, ele dispensa configurações, e já está pronto para uso. O máximo que você pode precisar fazer em termos de configuração é criar um //alias// com as opções que preferir (que são poucas). Mais a frente eu mostro como fazer isso para configurar um //prompt// para esse editor, o que tende a ser conveniente. ==== Desvantagens ==== Mas nem tudo é perfeito, e existem também algumas desvantagens: * **Curva de aprendizado** O editor ed não é muito intuitivo. O ideal é ler a documentação antes de usar (o que é uma boa prática, de qualquer modo). Se acostumar com o modo de fazer as coisas nele pode levar algum tempo. Se me perguntar, o esforço inicial se paga no longo prazo, mas não posso negar, leva algum tempo para pegar o jeito. Além disso, o uso de expressões regulares possui uma importância para esse editor. Expressões regulares facilitam muito as tarefas de pesquisa e edição de linhas, e portanto são um aprendizado a parte necessário para tirar o máximo do editor. O que talvez seja um efeito colateral positivo disso é que demonstrar proficiência com o ed pode inspirar alguma confiança entre seus pares, afinal mostra que você não quer tudo mastigado e se dispõe a "arregaçar as mangas" quando entende que isso é necessário. * **Costume com os modos** O multimodalismo também pode confundir às vezes. Você pode,em alguns momentos, se esquecer de que está no modo de comandos e inserir texto, o que emite um erro (a propósito, não tenha medo disso, não possui nenhuma consequência), e em outros pode estar no modo de entrada, e inserir um comando que depois precisará ser apagado. Novamente, isso é fácil de resolver, basta remover a linha onde o comando foi inserido. Com o tempo, essas confusões se tornam menos comuns e a reparação mais rápida. O uso de um //prompt// (mais detalhes adiante) também ajuda bastante a reduzir essa confusão. * **Um arquivo de cada vez** No ed, diferente de muitos editores, não é possível abrir e visualizar vários arquivos ao mesmo tempo. Mas convenhamos, você não estaria editando vários arquivos ao mesmo tempo. Se o que você precisa na verdade é visualizar o conteúdo de outro arquivo antes de tomar uma decisão sobre a edição que vai fazer no arquivo atual, isso pode ser feito no ed, basta usar o comando de execução de comandos (!) para exibir na tela (seja com cat, grep, less ou o que desejar) o conteúdo desse outro arquivo. * **Cuidado especial com caracteres de controle** Esse realmente é um problema enjoado. Ao inserir novo texto, você deve ter o cuidado de não inserir caracteres de controle por acidente (geralmente quando pressiona a tecla ''Ctrl'' por acidente enquanto digita). O resultado é que a linha visualmente parecerá perfeita, mas no meio dela pode constar algum desses caracteres não imprimíveis (portanto não visíveis). Eu costumo redobrar a atenção enquanto estou no modo de entrada ou fazendo alguma substituição, para evitar erros desse tipo. Mas vez ou outra pode acontecer. Felizmente, há um comando que mostra a linha de modo inequívoco, convertendo os caracteres não imprimíveis para uma representação octal, e existem também comandos que podem ser usados para fazer essa limpeza. Veremos como fazer isso. * **Não há quebra de linha automática** Um recurso útil para evitar que as linhas de um arquivo fiquem muito longas é a quebra de linha automática, que após atingir determinado ponto automaticamente quebra o texto para uma nova linha. Esse é um recurso que não existe no ed, infelizmente. Existem algumas formas de lidar com isso. Uma delas é aprimorar o "olhar clínico" para perceber se uma linha está muito longa. Outro recurso é usar o comando de substituição para quebrar linhas após determinado tamanho (não é perfeito mas ajuda). E ainda outro modo de lidar com isso é escrever a linha (ou as linhas) em um arquivo temporário, e depois ler esse arquivo aplicando um comando de formatação. Todos esses truques serão apresentados mais detalhadamente adiante. ==== Tirando o máximo ==== Eu sei que apenas falar nas vantagens e desvantagens ainda é um pouco vago e você pode estar se perguntando como tirar o máximo desse editor. Como aproveitar o máximo os pontos fortes e como minimizar o quanto for possível os pontos fracos? O intuito desse documento é remover as barreiras iniciais, mas a despeito disso, é importante que você evite comparar o ed com outros editores em um primeiro momento. Procure explorá-lo com a mente aberta e aceitar que no começo você terá pouco traquejo com ele. Isso será uma parte quase inevitável do processo, pois você provavelmente já se acostumou bastante com a edição visual. É natural que haja um "choque cultural". ==== Quando usar e quando não usar ==== Em geral, o ed é mais confortável para editar texto que já existe do que para criar texto novo, do zero. Isso faz dele uma opção mais interessante para editar arquivos de configuração e realizar ajustes em código-fonte. Ele também é uma opção interessante quando você precisa obter saídas de comandos e gravar em um arquivo, ou quando precisa fazer mudanças em um arquivo de script e testá-lo em seguida, sem sair do editor (e até mesmo antes de salvar as mudanças!). Redigir muitas linhas de texto pode não ser muito confortável e talvez seja melhor deixar essa tarefa para os editores visuais. Ao menos enquanto você não tiver mais prática com esse editor. Como já foi falado antes, o ed também é interessante para cenários mais restritos, como hardware limitado e sistemas mais minimalistas. Ele também é um editor comum para uso em imagens live de recuperação e para uso em modos de sistema protegidos, que possuem critérios mais rígidos de segurança. ===== Noções básicas ===== Para aprender a usar o ed, vamos começar detalhando alguns conceitos comuns da sua terminologia: * **Buffer** Um //buffer// é uma área de memória onde será armazenado temporariamente o conteúdo que você vai editar. Se você abrir um arquivo que já existe para edição, uma cópia dele vai ser feita e colocada nesse //buffer//. Quaisquer edições que fizer estarão apenas no //buffer//, e apenas no momento em que acionar o comando de escrita para salvar é que essas alterações serão replicadas no arquivo. Se você encerrar o ed sem acionar esse comando de escrita, as edições que tiver aplicado serão perdidas. No entanto, ele emite um alerta antes, para que você saiba que existem alterações não salvas. Existem comandos específicos para fechar ou limpar o buffer ignorando esse alerta. * **Comando** Um comando é uma ação a ser aplicada sobre o //buffer//. Existem comandos para exibir uma ou mais linhas, para alterar a posição atual, para alterar o conteúdo de uma linha, para listar linhas que se encaixam em algum padrão e opcionalmente realizar alguma operação sobre elas, comandos para copiar, mover ou remover linhas, comandos para marcar linhas, etc. Alguns comandos alteram o modo de edição (isto é, mudam do modo de comandos para o modo de entrada). * **Endereço** A rigor, um endereço é uma linha. Mas essa linha pode ser referenciada de formas diferentes. Pode ser pelo número da linha, pode ser pela ocorrência de algum texto dentro dela, pode ser por um marcador que foi aplicado a essa linha ou pode ser também pela sua posição em relação a alguma outra linha. Ao executar comandos, você pode informar um endereço (em alguns casos, dois). Isso serve para determinar sobre qual linha o comando deve operar, ou sobre um conjunto de linhas entre uma linha inicial e uma final, incluindo ambas. Você pode por exemplo, executar o comando d (que serve para remover uma linha) sobre a linha 3 (''3d''), sobre a próxima linha (''+d''), sobre a última linha (''$d''), sobre a linha que possui o texto "abacaxi" (''/abacaxi/d'') ou sobre a linha que possui o marcador b ('''bd''). Perceba que o comando é antecedido pelo endereço de uma linha. Sempre que um endereço é omitido, um valor default será determinado para ele. Esse valor default pode variar conforme o comando. Veremos mais detalhes sobre isso depois. * **Expressão regular** Uma expressão regular é uma forma de representar um ou mais textos possíveis, que se encaixam em um padrão. Ao pesquisar por algum texto, podemos fazer uma pesquisa literal, isto é, que seja exatamente aquele texto, mas também podemos pesquisar por qualquer texto que possua determinadas características (por exemplo, pesquisar por linhas que sejam compostas por 3 palavras). A sintaxe das expressões regulares varia conforme a implementação do interpretador das expressões. O padrão POSIX prevê [[https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap09.html|duas formas de expressões regulares]], as expressões básicas e as expressões estendidas. O ed utiliza as expressões básicas. * **Marcador** Um marcador funciona como uma forma fácil de se lembrar de alguma linha. Isso é útil quando, no lugar de se lembrar do número da linha, for mais fácil se lembrar de uma letra representativa do conteúdo daquela linha. Acredite, depois de navegar por algum tempo em um texto, você facilmente se esquecerá do número de uma linha que possuía algo importante, mas terá facilidade para se lembrar que marcou essa linha com a letra "a" (ou qualquer letra que tiver escolhido). Marcadores também são úteis para realizar operações comuns, como mover um grupo de linhas para outro local. Você pode marcar o ponto A e o ponto B (com os marcadores a e b), e depois no momento de executar o comando de movimentação (''m''), não precisa se lembrar os números das linhas de início e fim, basta usar os marcadores. Outra vantagem de marcadores é que eles são vinculados à linha e não ao número da linha. Se você remover linhas que antecedem a linha marcada ou adicionar novas linhas antes dela, o marcador continuará apontando para a mesma linha, mesmo que ela tenha outro número. Mas saiba de antemão que se você aplicar alterações sobre a linha marcada, o marcador será removido. É importante lembrar também que marcadores só são válidos enquanto o arquivo está carregado no //buffer//. No momento em que encerrar o editor ed ou carregar algum outro arquivo no //buffer//, todos os marcadores serão perdidos. * **Modo** Conforme já explicado, o ed é um editor multimodal. Um modo representa um estado do editor, que no caso do ed servirá para determinar que o texto inserido seja tratado como comando (no modo de comandos) ou como texto normal (no modo de entrada). Ao iniciar, o editor ed estará no modo de comandos. Apenas três comandos podem acionar o modo de entrada: o comando de inserção (''i''), o comando de adição (''a'') e o comando de mudança (''c''). Nas linhas seguintes a esses comandos, todo o texto inserido será texto normal. Para voltar ao modo de comandos, será necessário informar uma linha que contenha apenas um ponto (''.''). * **Parâmetro** Alguns comandos podem (ou devem) ser parametrizados. Por exemplo, o comando ''e'' carrega um arquivo no //buffer//. Se nenhum parâmetro for informado, ele apenas recarrega o arquivo atual (supondo que haja um). Mas para carregar um arquivo diferente, é preciso informar que arquivo será esse. Essa informação é fornecida via parâmetro, que é fornecidos após o comando (por exemplo, ''e meu_arquivo.txt''). Em alguns casos, o parâmetro a ser informado pode também ser um endereço. Por exemplo o comando de transferência (''t''), que copia uma ou mais linhas para um local de destino, recebe como parâmetro o local de destino. Mais detalhes sobre a estrutura de um comando e o uso de parâmetros serão explorados depois. * **Pesquisa** Uma operação de pesquisa buscará um determinado padrão de texto ao longo de todo o //buffer//, e retornará a linha correspondente à próxima ocorrência, caso haja alguma. Caso não haja, entre a posição atual e o fim do buffer, nenhuma ocorrência, a pesquisa seguirá a partir do início, até a posição atual, e retorna um erro, caso não encontre nada. Uma operação de pesquisa funciona não apenas como uma forma de encontrar texto, mas também como uma forma de endereço, para que algum comando seja executado. Ao realizar uma pesquisa, você pode aplicar um comando sobre a linha retornada. Aliás, um comando sempre será aplicado: por default será o comando ''p'', que mostra a linha, caso nenhum comando tenha sido informado na pesquisa. Uma pesquisa pode ser seguir o caminho normal, para "a frente" no texto, ou o caminho inverso, "para trás". * **Posição** No editor ed existe a noção de uma posição atual dentro do //buffer//. Um //buffer// pode ser composto por zero ou mais linhas . A posição zero é especial, no sentido de que não é propriamente uma posição, mas sim a condição de "antes da primeira linha", o que pode servir para algumas operações. E é a única posição que existe em um //buffer// vazio. Caso haja ao menos uma linha, alguma posição real será determinada. Ao abrir um arquivo, a posição será automaticamente configurada para a última linha do arquivo, e pode ser alterada a qualquer momento, bastando informar o endereço desejado. Vários comandos alteram a posição atual após sua execução. Por exemplo, os comandos que alternam para o modo de entrada, após execução alteram a posição atual para a última linha fornecida. * **Prompt** Um //prompt// é um texto (de um ou mais caracteres) que sinaliza que o editor está à espera de um comando. Como comentei antes, é fácil se confundir entre os modos de comandos e de entrada. O uso de um //prompt// serve para desfazer essa confusão, deixando explícito que se está no modo de comandos. Por padrão, o editor ed inicia sem um //prompt//. Você pode ativar/desativar o //prompt// (com o comando ''P''). No modo de entrada, o //prompt// não é emitido, facilitando a diferenciação entre os modos. É possível reconfigurar o texto a ser usado no //prompt//, e ao fazer isso o ed já inicia com ele ativado. Veremos mais detalhes sobre isso adiante nesse documento. * **Redirecionamento** No ed, é possível interagir com outros comandos do sistema, tanto para leitura como para escrita. No caso da leitura, o ed aciona um comando do sistema, e lê a sua saída, que é gravada no //buffer//, ou seja, a saída do comando executado é redirecionada para o //buffer//. Isto é feito com o comando ''r''. Já no caso da escrita, todo ou parte do //buffer// é redirecionado para algum comando externo, que opera sobre esse conteúdo. Isto é muito útil, por exemplo, para direcionar o conteúdo de um script para o interpretador, e pode ser feito até mesmo sem que ele tenha ainda sido salvo, pois o conteúdo do buffer (e não necessariamente do arquivo) é que estaria sendo fornecido. Isto é feito com o comando ''w''. O detalhamento desses (e de outros) comandos será feito mais adiante, e na ocasião esses redirecionamentos serão melhor explicados com exemplos. * **Substituição** A informação de posição do ed é referente apenas a linhas, mas não existe a noção de navegação dentro de uma linha, avançando ou retrocedendo entre caracteres. Portanto, para alterar o conteúdo de uma linha, é preciso usar comandos de substituição, que pesquisam por um padrão de texto na linha, e então caso encontre esse padrão, substitua por algum outro texto. É possível alterar uma ocorrência de cada vez, reexecutando o mesmo comando, ou usando um modificador (''g'') que aplica a alteração a todas as ocorrências de uma só vez. O comando ''s'' é o responsável por aplicar substituições, e ele possui uma estrutura um pouco diferente dos demais comandos. ===== Iniciando e encerrando ===== Muito bem, já vimos os conceitos principais, agora é hora de um pouco de prática. Vamos começar pelo básico que é iniciar e encerrar o editor ed. A propósito, não saber encerrar um editor pode causar um certo pânico, então vamos tratar disso logo. Para iniciar o editor ed, vamos começar com um exemplo simples, sem abrir nenhum arquivo, apenas iniciar o editor com um //buffer// vazio. Você verá uma linha vazia, na qual um comando pode ser inserido. Então você aprenderá o seu primeiro comando agora, o comando ''q'' (//quit//), que encerra o editor. Nessa linha vazia, digite q, e o editor será encerrado. $ ed q $ 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). 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: $ ed -p '* ' * q $ Aqui usei um asterisco seguido de espaço, mas fica a seu critério qual texto acha melhor como //prompt//. Desaconselho o uso de interrogação, pois esse sinal já é usado para emitir mensagens de diagnóstico, e também é útil usar um espaço como último caractere do prompt, para não misturar com o comando. Para não ter que usar esse parâmetro ''-p'' toda vez que iniciar o ed, você pode configurar um //alias// para o ele (dependendo de qual shell utilizar, pode haver variações na forma de fazer isso): alias ed='ed -p "* "' Nos exemplos seguintes partirei da premissa de que o //alias// do exemplo acima está configurado. Antes de prosseguir, tenho apenas mais um assunto para comentar sobre //prompts//: você pode, a qualquer momento dentro do editor, desabilitar ou reabilitar o //prompt// com o comando ''P'': $ ed * P P * q $ Para quê desabilitar o //prompt//? Eu realmente não consigo imaginar um bom motivo, mas caso você tenha se esquecido de configurá-lo previamente, e esteja editando um arquivo, pode ser útil lembrar que ele pode ser ativado a qualquer momento. Apenas tenha em mente que por padrão o prompt usado é um asterisco (''*'') sem um espaço depois, o que visualmente pode causar algum desconforto por misturar o //prompt// ao comando, então é mais interessante configurá-lo antes de iniciar o editor, como apontei antes. ===== 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. A título de exemplo, consideremos um arquivo de texto, contendo o texto: Editor minimalista nunca te deixa na mão, seja em PC de batata ou em PC de milhão. Veremos exemplos das duas formas, começando pelo primeiro caso (já informar o nome do arquivo ao iniciar): $ ed poema_ed.txt 85 * O que houve aqui? O que é esse 85? Trata-se do número de bytes que foram lidos. Isso não equivale necessariamente ao número de caracteres, pois quaisquer quebras de linha e acentos ou cedilhas também são contabilizados. Mais importante do que saber quantos bytes foram lidos é saber que foram lidos. Você pode entender essa mensagem como uma confirmação de que o arquivo de fato foi carregado no //buffer//. 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: $ ed * e poema_ed.txt 85 * Simples. O efeito prático é o mesmo. O arquivo é carregado no //buffer// e estará pronto para leitura e edição, e o nome do arquivo será configurado. "Espere! Nome do arquivo configurado? Como assim?" Já imagino que esteja se perguntando. Ocorre que o ed guarda consigo a informação de nome de arquivo, para saber onde escrever as modificações feitas no //buffer//. 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 atual, usamos o comando ''f''. Um erro será emitido se o nome não estiver preenchido ainda. $ ed * f ? * e poema_ed.txt 85 * f poema_ed.txt * 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. Podemos a qualquer momento usar esse mesmo comando ''f'' para trocar o nome atual. 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. 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). $ ed poema_ed.txt 85 * f poema_ed.txt * e outro_arquivo.txt 36 * f outro_arquivo.txt * e nao_existe.txt ? * f nao_existe.txt * 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. 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. A título de curiosidade, perceba uma similaridade entre os comandos ''q'' e ''e'', e entre os comandos ''Q'' e ''E''. Os comandos em letra minúscula, por poderem incorrer em perda de alterações emitem um alerta. O equivalente em letra maiúscula desconsidera essa possível perda. Isto não é por acaso. Há uma consistência na escolha do que cada comando significa, e você ainda perceberá outros exemplos dessa consistência, que não são mera coincidência. ===== Lidando com erros ===== Errar é humano, e aprender com os erros também. Porém, é preciso compreender onde errou e porque determinada ação foi um erro. Nisso o ed pode te ajudar. Quando você executa um comando inválido, informa parâmetros inválidos para um comando, ou executa um comando que não faz sentido em determinado contexto ou que pode ter consequências ruins, o ed emite uma mensagem de erro (ou de alerta). Como já vimos, ele é bem sucinto e apenas exibe um sinal de interrogação, que apenas indica que algo está errado. Mas como saber o que foi? Para isto, podemos usar o comando ''h'', que detalha o último erro, exibindo sua mensagem. Vamos voltar a um exemplo que já vimos (tentar mostrar o nome de um arquivo quando não há nenhum): $ ed * f ? * h no current filename * **Obs.:** as mensagens podem ter algumas variações conforme a implementação do ed, e também conforme as configurações de idioma no sistema. Não é possível ver todas as mensagens de erro anteriores, apenas a mais recente (não que haja muita utilidade em ver todas as mensagens de erro passadas). Pessoalmente, vejo certa elegância nesse estilo de diagnóstico, ou seja, apenas quando solicitado. Mas se você prefere que as mensagens de erro sejam sempre emitidas, pode usar o comando ''H''. Isto fará com que todas as mensagens de erro seguintes sejam exibidas de imediato. $ ed * H * f no current filename * e no current filename * q $ Lembra quando falei sobre as mensagens de alerta quando você tenta fechar ou limpar o //buffer// (comandos ''q'' e ''e'') e com isso perder alterações não salvas? Pois bem, o ed usa esse sistema de diagnóstico para mostrar que existem alterações não salvas. Vamos supor que você tenha um //buffer// aberto com alterações que aplicou e não salvou. O que acontece se você tentar encerrar o editor? Vejamos: * q ? * h warning: file modified * q $ Note que na segunda execução do comando ''q'' ele prossegue com o encerramento. ==== Uma nota sobre alertas ==== 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á. 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. ===== Indo e voltando ===== Até agora só vimos como abrir um arquivo no ed, mas não fizemos nada, nem leitura nem escrita. Vamos então começar com o básico da leitura, que é usar endereços para avançar e/ou retroceder sobre o texto. A princípio os conceitos podem parecer bem rudimentares, mas eles serão importantes para que depois você possa fazer um uso mais efetivo do editor. Recapitulando os conceitos, o ed possui uma noção de posição dentro do texto, sendo a posição uma linha específica. Ao abrir o editor, você estará na última linha do //buffer//, ou na posição zero, se o //buffer// estiver vazio. Para saber que linha é essa (última ou zero), você pode usar o comando ''=''. $ ed * = 0 * q $ ed poema_ed.txt 85 * = 4 * q $ Isso já é um primeiro passo no senso de localização dentro do texto. Mas como ir para outras linhas? Para isso, usamos endereços que apontam para essas linhas. O mais simples deles é informar o número da linha. Ao informar ''1'' você irá para a primeira linha. Como você já sabe qual é a última linha, sabe também quais são as linhas possíveis de serem informadas (de 1 a 4 nesse caso). $ ed poema_ed.txt 85 * 1 Editor minimalista * 2 nunca te deixa na mão, * Eu sei. Isso não parece muito conveniente, você não quer números de linhas e //prompts// atrapalhando a leitura do texto. Nem eu. Logo mais vamos ver como mostrar linhas em sequência. Por hora, atenha-se ao fato de que podemos informar um número de linha como endereço, e isso faz com que o editor nos leve a essa linha. Existem outras maneiras de apontar para uma linha, sem ser pelo seu número. Se usarmos o ponto (''.'') como endereço, apenas apontamos para a linha atual. No exemplo a seguir continuamos de onde paramos no anterior (linha 2): * . nunca te deixa na mão, Não parece muito útil. Mas novamente, atenha-se ao significado do endereço (linha atual). Existem também o endereço da próxima linha, que denotamos com o mais (''+''), e o da linha anterior, com o sinal de menos (''-''). * + seja em PC de batata * - nunca te deixa na mão, * Você pode especificar ainda algo como "duas linhas à frente" (''+2'') ou "três linhas para trás" (''-3''): * +2 ou em PC de milhão. * -3 Editor minimalista * Ou seja, você pode quantificar quantas linhas quer avançar ou retroceder. Digamos que em algum momento você já se esqueceu de quantas linhas avançou ou voltou e não sabe o número da linha atual. É possível verificar? Claro! Novamente, usando o comando ''='', mas especificando que quer ver o número da linha atual (cujo endereço é o ponto). * .= 1 * Olha só! Não é que esse ponto tem utilidade? E isso é só o começo. Podemos determinar um endereço antes do operador de igual para mostrar a qual linha ele se refere. Por padrão, ele mostra a última, mas se antecedido por um endereço, retorna a linha desse endereço. Veremos mais detalhes sobre essa estrutura de comandos na seção seguinte. Mas seguindo na explicação sobre endereços, existe também um endereço para a última linha. Para ele, usamos o cifrão (''$''). * $ ou em PC de milhão. * Existem ainda outras formas de endereçamento que vamos explorar, mas que dependem da explicação de novos conceitos. Agora já podemos falar um pouco mais sobre os comandos que podemos usar e como tirar melhor proveito desses endereços que aprendemos. ===== A estrutura dos comandos ===== Um fato interessante sobre os comandos do ed é que todos eles são apenas uma letra (exceto ''='' e ''!'' que ainda veremos, pois não são letras). São poucos comandos o bastante para que isso seja possível. A composição desses comandos varia um pouco. Alguns são precedidos por um endereço, outros por dois, e outros por zero. Da mesma forma, alguns aceitam (ou necessitam) um parâmetro, e outros não. Resumindo: [endereço[,endereço]]comando[parâmetros] Comandos que aceitam zero endereços (''q'', ''Q'', ''e'', ''E'', ''f'', ''h'', ''H'', ''P'', ''u'' e ''!'') nunca devem ser precedidos por um endereço, pois isso é tratado como um erro pelo editor. Os comandos que trabalham com um endereço podem ser precedidos de mais endereços, que serão ignorados, e apenas o último deles será considerado. Os que trabalham com dois considerarão os dois últimos, e ignorarão os demais. Tanto os de um como os de dois endereços possuem valores //default// para os endereços, caso não sejam fornecidos. Por exemplo, o comando ''='' usa apenas um endereço (por padrão, o último, isto é, ''$''). Portanto, se nenhum endereço é fornecido, ele usa o último. Se algum endereço preceder o comando, ele usará esse endereço (vimos o exemplo com o endereço da linha atual anteriormente), e se mais endereços forem fornecidos, eles serão ignorados (a não ser que algum deles seja inválido, o que retornará um erro). $ ed poema_ed.txt * = 4 * 3= 3 * 1,3= 3 * 3,1= 1 * 5,3,1= ? * h invalid address * Mas afinal, por que alguns comandos usam só um endereço, e outros usam dois? Simples: porque um endereço serve para uma linha, enquanto dois endereços definem um intervalo de linhas incluindo a do primeiro endereço, a do segundo, e todas que existirem entre elas. Importante lembrar que nesses casos, o segundo endereço deve representar uma linha de número maior que a do primeiro. Já vamos ver como trabalhar com dois endereços, mas para isso precisamos apresentar mais um comando, que serve para mostrar o conteúdo de uma linha. Mas já não fizemos isso ao informar os endereços das linhas? Ao visitar uma linha, você deve ter notado que ela sempre é exibida. Não mencionei esse fato, mas isso ocorre porque a ação padrão no ed é a de mostrar a linha, mas você pode usar um comando explícito para mostrar uma linha, o comando ''p''. Para uma única linha, tanto faz usar esse comando ou não, pois já é a ação padrão. Ou seja, tanto faz usar o comando ''1'' ou ''1p'' para mostrar a primeira linha. Agora, quando queremos mostrar um trecho de duas ou mais linhas, aí precisamos desse comando. E ele aceita dois endereços para mostrar um intervalo de linhas. Então agora temos um modo de mostrar todo o conteúdo do arquivo de uma vez, comandos no meio. $ ed poema_ed.txt * 1,4p Editor minimalista nunca te deixa na mão, seja em PC de batata ou em PC de milhão. * Bingo! Agora está ficando mais interessante. Mas como eu falei, ed é uma ferramenta sucinta e elegante, e existe um modo ainda mais prático de mostrar todo o conteúdo do //buffer//, usando apenas uma vírgula para denotar que o comando se aplica "do início ao fim". * ,p Editor minimalista nunca te deixa na mão, seja em PC de batata ou em PC de milhão. * q $ O comando '',p'' é um dos que você mais vai usar para textos pequenos, que cabem por inteiro na tela. Mas existem várias combinações interessantes que podemos fazer para definir intervalos. Por exemplo, podemos usar ''.,+2'' para dizer "da linha atual até a linha duas posições depois", e ''-,+'' para "da linha anterior até a próxima linha". É importante saber que ao mostrar um intervalo de linhas, a posição dentro do //buffer// será ajustada para a última linha exibida. $ ed poema_ed.txt * .,+2p Editor minimalista nunca te deixa na mão, seja em PC de batata * .= 3 * -,+p nunca te deixa na mão, seja em PC de batata ou em PC de milhão. * .= 4 * Na tabela a seguir, podemos ver mais algumas combinações com seus significados: ^ Atalho ^ Equivale a ^ Significado ^ | '','' | ''1,$'' | Do início ao fim | | '',.'' | ''1,.'' | Do início até aqui | | '',3'' | ''1,3'' | Do início à terceira | | '',+3'' | ''1,4'' | Do início às três próximas | | ''3,+3'' | ''3,(.+3)'' | Da terceira até as três próximas | | '';'' | ''.,$'' | Daqui até fim | | '';3'' | ''.,3'' | Daqui até a terceira | | '';+3'' | ''.,(.+3)'' | Daqui até as três seguintes | | ''3;+3'' | ''3,6'' | Da terceira até as três seguintes | Perceba que no lugar da vírgula podemos usar o ponto-e-vírgula ('';'') para separar os endereços. Existe uma mudança no significado? Depende. Se especificar dois endereços fixos (os números propriamente), não fará diferença usar a vírgula ou o ponto-e-vírgula. Mas se usar endereços relativos como a linha atual (''.'') ou a próxima linha (''+'') por exemplo, aí faz diferença. A diferença é que na separação por ponto-e-vírgula, o segundo endereço é relativo ao primeiro. Portanto a noção de próxima linha, por exemplo, é em referência ao endereço da primeira linha informada. Então, por exemplo, podemos mostrar a segunda e a terceira linha, como a seguir. * 2;+p nunca te deixa na mão, seja em PC de batata * Note que nesse caso o segundo endereço informado é o próximo em relação ao primeiro (linha 2), portanto 3. Muito bem, agora você já sabe se localizar no texto, navegar pelas linhas e exibir o conteúdo das linhas, seja uma a uma ou várias de uma vez. Sugiro que tome um tempo para praticar com o que aprendeu até aqui, antes de passar para os próximos tópicos. ===== Inserindo, adicionando e alterando linhas ===== Até aqui só tratamos sobre a leitura dos arquivos. Agora vamos começar a falar em escrita. E para isso vamos precisar recapitular a discussão sobre multimodalidade. Como falei, o ed é um editor que possui dois modos, e até aqui só usamos o modo de comandos, ou seja, inserimos um comando e o ed realiza alguma operação. Agora, vamos começar a ter contato com a troca de modos, mudando do modo de comando para o de entrada, e depois voltando para o de comandos. Os comandos que apresentarei agora são os únicos que realizam essa troca: o comando ''i'' para inserção de texto (antes do endereço informado), o comando ''a'' para adição de texto (depois do endereço informado) e o comando ''c'' para alteração de texto (substituindo uma ou mais linhas, conforme o endereço ou endereços fornecidos). Quando acionados, esses comandos iniciam o modo de entrada (no qual não haverá //prompt//), e todo o texto que você digitar será tratado como texto a ser inserido no //buffer//. Para terminar, basta inserir um ponto na última linha (sem nada antes ou depois). Esses três comandos, como falei antes, possuem um endereço padrão (o da linha atual). Caso o //buffer// esteja vazio, a posição atual é zero (o que é um valor aceitável para ''a'' e ''i'', mas não para ''c''). Quando usamos o endereço zero, os comandos ''a'' e ''i'' tem exatamente o mesmo efeito. Só percebemos a diferença quando usamos um endereço "real". Vejamos um exemplo: $ ed * i primeira linha . * 0a não, essa é a primeira linha . * ,p não, essa é a primeira linha primeira linha * Perceba que depois dos comandos ''i'' ou ''a'', não há //prompt//. Todas as linhas seguintes são tratadas como texto normal. Quebras de linha são preservadas. Somente quando uma linha com um ponto isolado é fornecida que se retorna para o modo de comandos. Perceba também que nos dois casos (isto é, tanto ao inserir como ao adicionar) o conteúdo da primeira linha foi o último fornecido. Isso acontece porque inserir antes ou depois da posição zero de qualquer modo vai inserir antes da primeira linha do //buffer//. Portanto os comandos ''0i'', ''1i'' e ''0a'' fazem exatamente a mesma coisa na prática. Já os comandos ''1i'' e ''1a'' diferem no fato de que ''1i'' insere antes da primeira linha, mas ''1a'' insere o texto depois da primeira linha. * 1 não, essa é a primeira linha * a segunda linha . * ,p não, essa é a primeira linha segunda linha primeira linha * Neste exemplo eu poderia ter usado ''1a'' diretamente em vez de separar em dois comandos ''1'' e ''a''. Apenas quis frisar que ''a'' atua sobre a posição atual, que neste exemplo é 1. Vejamos agora o comando de alteração, ''c''. Por padrão, como eu disse, ele atua sobre a posição atual, substituindo o conteúdo dessa linha pelo texto que será fornecido (podendo ele ter uma ou mais linhas). * 3 primeira linha * c terceira linha . * ,p não essa é a primeira linha segunda linha terceira linha * Aqui, do mesmo modo poderia ter usado ''3c'' diretamente no lugar de ir para a linha 3 primeiro e só substituir depois. Assim como o comando ''p'' que vimos antes, ''c'' pode usar um ou dois endereços. Se forem dois, ele substitui todas as linhas desde o primeiro endereço até o segundo. * ,c Nada do que estava escrito antes importa. Apaguei tudo e agora o texto será outro. . * ,p Nada do que estava escrito antes importa. Apaguei tudo e agora o texto será outro. * Percebeu o que aconteceu aqui? Usei apenas uma vírgula para definir dois endereços (recapitulando, uma vírgula equivale a ''1,$'', isto é, do início ao fim), portanto podemos usar esse comando para apagar todo o arquivo e fornecer outro conteúdo no lugar dele. ===== Persistindo mudanças ===== Depois de fazer modificações em um //buffer// em algum momento você eventualmente vai querer salvar essas modificações para não perdê-las quando fechar o editor. Para isso usaremos o comando ''w''. Mas atenção, para que ele funcione, ele precisa de um parâmetro. Lembra-se de quando falei na estrutura dos comandos que alguns usam parâmetros? Esse comando é mais um deles. Novamente, o parâmetro será um nome de arquivo, o arquivo onde você quer escrever. Do mesmo modo como vimos com os comandos ''e'', ''E'' e ''f'', o comando ''w'' possui um valor //default// para esse parâmetro, caso o editor já esteja trabalhando sobre algum arquivo, isto é, se você abriu o editor ed informando algum arquivo ou carregou algum arquivo com ''e''. Caso contrário, ele ainda não possui um nome de arquivo e tentar escrever sem passar um nome de arquivo será um erro. Vamos continuar no exemplo da seção anterior, onde estávamos trabalhando sobre um //buffer// anônimo. * w ? no current filename * w qualquer_coisa.txt 84 * f qualquer_coisa.txt * q $ Veja que precisei informar um nome de arquivo (que foi criado ao escrever o //buffer//). Eu poderia fornecer o nome de um arquivo que já existe, mas nesse caso o conteúdo do arquivo seria perdido e substituído pelo conteúdo do //buffer//, então é bom ter um pouco de cuidado ao escrever, e prestar atenção onde está escrevendo. Se estiver com receio de escrever um arquivo por não ter certeza se ele já existe, há um modo de verificar isso. Mas isso é assunto para outra seção, onde trataremos execução de comandos. Outro detalhe a comentar sobre essa operação é que, assim como acontece quando carregamos um arquivo no //buffer//, quando escrevemos o conteúdo do //buffer// em um arquivo, recebemos uma mensagem informando o número de //bytes// escritos (nesse exemplo, 84). Novamente, isso também funciona como um indicativo de que a operação deu certo. Note que depois de escrever, o nome de arquivo passa automaticamente a ser o do arquivo recém-escrito. Mas convém lembrar que se já existia um nome de arquivo configurado, escrever em outro arquivo não vai alterar o nome atual. $ ed qualquer_coisa.txt 84 * w backup.txt 84 * f qualquer_coisa.txt * Como pode perceber, isso é útil para salvar um //backup//, e continuar editando o arquivo atual. Caso você realmente queira alterar o nome do arquivo atual para outro, pode usar o próprio comando ''f'' para isto: * f outro_arquivo.txt * w 84 * q $ Veja que após alterar o nome do arquivo, o comando ''w'' foi usado sem parâmetros. Isso escreveu em ''outro_arquivo.txt'', pois este era o nome configurado no momento da escrita. Agora, lembra-se do que falei sobre os alertas no ed? Vamos recapitular agora que já conhecemos o comando ''w''. Ao aplicar mudanças no //buffer//, o ed considera que há mudanças não salvas. Se você tentar fechar normalmente o editor (isto é, com ''q'') ou carregar normalmente outro arquivo (com ''e''), ele emitirá um alerta e considerará que o alerta já foi dado. Pois bem, no momento em que você escrever o conteúdo do //buffer// em um arquivo (seja o arquivo atual ou outro), ele passa a considerar que não há mais nenhuma mudança não salva (ou seja, que é seguro encerrar ou carregar outro arquivo), e a partir desse ponto, para qualquer alteração que você fizer o ed vai considerar que você ainda não foi alertado, caso tente usar ''q'' ou ''e'', e vai emitir o alerta novamente. ===== Mais comandos de visualização ===== ...