utils:ed
Diferenças
Aqui você vê as diferenças entre duas revisões dessa página.
Ambos lados da revisão anteriorRevisão anteriorPróxima revisão | Revisão anterior | ||
utils:ed [2024/12/25 19:54] – [Iniciando e encerrando] ajuste tipográfico hrcerq | utils:ed [2025/01/19 13:26] (atual) – [Uma nota sobre alertas] transformado em nota hrcerq | ||
---|---|---|---|
Linha 6: | Linha 6: | ||
Em resumo, o __ed__ é muito versátil, amplamente disponível, | Em resumo, o __ed__ é muito versátil, amplamente disponível, | ||
- | ===== História ===== | ||
- | |||
- | 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 (em 1969), 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. | ||
- | |||
- | ===== Padronização ===== | ||
- | |||
- | O __ed__ é parte do padrão POSIX. Presente nas seguintes revisões: | ||
- | |||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | |||
- | ===== Implementações ===== | ||
- | |||
- | Existem diferentes implementações do __ed__. Algumas delas são: | ||
- | |||
- | * [[https:// | ||
- | * [[https:// | ||
- | * [[http:// | ||
- | * [[https:// | ||
- | * [[https:// | ||
- | |||
- | Como reflexo da simplicidade deste editor, todas as implementações acima, exceto a do Busybox, aderem totalmente ao proposto no padrão POSIX, e a maioria delas inclui também algumas funcionalidades fora do padrão, como paginadores e atalhos para repetir substituições, | ||
===== Prós e contras ===== | ===== Prós e contras ===== | ||
Linha 66: | 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 | + | Por ser um editor multimodal, não é preciso utilizar combinações de teclas usando |
* **Não possui dependências** | * **Não possui dependências** | ||
- | Por ser um editor minimalista, | + | Por ser um editor minimalista, |
+ | |||
+ | Não possuir dependências significa que mesmo em modo monousuário do UNIX ele pode ser utilizado. Não por acaso ele geralmente | ||
< | < | ||
- | Cabe destacar que isso é um detalhe de implementação, | + | **Melhor dizendo**\\ |
+ | \\ | ||
+ | Cabe destacar que isso é um detalhe de implementação, | ||
\\ | \\ | ||
O ponto a ser frisado aqui é que a especificação do __ed__ é simples o bastante para que ele seja implementado sem necessidade de bibliotecas externas e ainda assim consiga atender os requisitos da especificação. | O ponto a ser frisado aqui é que a especificação do __ed__ é simples o bastante para que ele seja implementado sem necessidade de bibliotecas externas e ainda assim consiga atender os requisitos da especificação. | ||
Linha 219: | Linha 196: | ||
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. | 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 | + | 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 |
< | < | ||
Linha 227: | Linha 204: | ||
</ | </ | ||
- | Ufa! Agora você já sabe encerrar o editor, quando precisar. Mas vou além: o comando | + | Ufa! Agora você já sabe encerrar o editor, quando precisar. Mas vou além: o comando |
- | É importante frisar que digitar | + | É importante frisar que digitar |
- | 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 | + | 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 |
< | < | ||
Linha 241: | Linha 218: | ||
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, | 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, | ||
- | Para não ter que usar esse parâmetro | + | Para não ter que usar esse parâmetro |
< | < | ||
Linha 249: | Linha 226: | ||
Nos exemplos seguintes partirei da premissa de que o //alias// do exemplo acima está configurado. | 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 // | + | Antes de prosseguir, tenho apenas mais um assunto para comentar sobre // |
< | < | ||
Linha 261: | Linha 238: | ||
Para quê desabilitar o //prompt//? Eu realmente não consigo imaginar um bom motivo, mas caso você tenha se esquecido de configurá-lo previamente, | Para quê desabilitar o //prompt//? Eu realmente não consigo imaginar um bom motivo, mas caso você tenha se esquecido de configurá-lo previamente, | ||
- | Apenas tenha em mente que por padrão o prompt usado é um asterisco ('' | + | 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 ===== | ===== 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: | + | 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: |
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 287: | 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 | + | Digamos que você iniciou o editor com um //buffer// vazio. Você pode então usar o comando |
< | < | ||
Linha 298: | Linha 275: | ||
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á memorizado. | 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á memorizado. | ||
- | " | + | " |
- | 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, | + | 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, |
- | Para visualizar o nome memorizado, usamos o comando | + | Para visualizar o nome memorizado, usamos o comando |
< | < | ||
Linha 315: | Linha 292: | ||
</ | </ | ||
- | 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 | + | 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 |
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 | + | Você pode, a qualquer momento, usar o comando |
< | < | ||
Linha 339: | 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 | + | Caso já tenha certeza de que não quer salvar nada, pode usar o comando |
- | Tanto o comando | + | Tanto o comando |
- | < | + | < |
A título de curiosidade, | A título de curiosidade, | ||
\\ | \\ | ||
Linha 352: | Linha 329: | ||
===== Lidando com erros ===== | ===== 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). | + | 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__ |
- | Como já vimos, ele é bem sucinto e apenas exibe um sinal de interrogação, | + | Como já vimos, ele é bem sucinto e apenas exibe um sinal de interrogação, |
< | < | ||
Linha 365: | Linha 342: | ||
</ | </ | ||
- | **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. | + | **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, | + | 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, |
< | < | ||
Linha 380: | Linha 357: | ||
</ | </ | ||
- | Lembra quando falei sobre as mensagens de alerta quando você tenta fechar ou limpar o //buffer// (comandos | + | Lembra quando falei sobre as mensagens de alerta quando você tenta fechar ou limpar o //buffer// (comandos |
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: | 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: | ||
Linha 393: | Linha 370: | ||
</ | </ | ||
- | Note que na segunda execução do comando | + | Note que na segunda execução do comando |
- | ==== 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__ | |
- | 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__ | |
- | 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__ | ||
+ | </ | ||
===== Indo e voltando ===== | ===== 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, | + | 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, |
- | 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 | + | Recapitulando os conceitos, o __ed__ |
< | < | ||
Linha 422: | Linha 401: | ||
</ | </ | ||
- | 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 | + | 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 |
< | < | ||
Linha 436: | Linha 415: | ||
Eu sei. Isso não parece muito conveniente, | Eu sei. Isso não parece muito conveniente, | ||
- | Existem outras maneiras de apontar para uma linha, sem ser pelo seu número. Se usarmos o ponto ('' | + | 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): |
< | < | ||
Linha 443: | Linha 422: | ||
</ | </ | ||
- | 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 ('' | + | 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 (**-**). |
< | < | ||
Linha 453: | Linha 432: | ||
</ | </ | ||
- | Você pode especificar ainda algo como "duas linhas à frente" | + | Você pode especificar ainda algo como "duas linhas à frente" |
< | < | ||
Linha 466: | Linha 445: | ||
< | < | ||
- | Além do sinal de menos ('' | + | Além do sinal de menos (**-**) para voltar, podemos usar também o acento circunflexo (**^**) para o mesmo efeito. Porém ele não é exatamente um consenso entre implementações, |
</ | </ | ||
- | Agora, 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 | + | Agora, 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 |
< | < | ||
Linha 481: | Linha 460: | ||
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. | 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 ('' | + | 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 (**$**). |
< | < | ||
Linha 490: | Linha 469: | ||
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. | 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 ===== | ===== A estrutura dos comandos ===== | ||
Linha 741: | Linha 721: | ||
===== Mais comandos de visualização ===== | ===== Mais comandos de visualização ===== | ||
- | Até aqui você só utilizou o comando | + | Até aqui você só utilizou o comando |
- | O primeiro deles é o comando | + | O primeiro deles é o comando |
< | < | ||
Linha 764: | Linha 744: | ||
</ | </ | ||
- | 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 | + | 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 |
- | Agora vamos ver o outro comando, | + | Agora vamos ver o outro comando, |
O que quer dizer " | O que quer dizer " | ||
Linha 779: | Linha 759: | ||
</ | </ | ||
- | 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 ('' | + | 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, | + | Caracteres |
- | 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 | + | 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. |
- | Porém, com o comando '' | + | 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 |
- | Mas o comando | + | 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 | ||
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 |
- | Portanto, o ed pode ser muito útil como uma ferramenta de inspeção de arquivos. | + | Portanto, o __ed__ |
- | Ainda outra situação onde esse comando vem a calhar é quando você quer saber se existem espaços no final da linha. O comando | + | Ainda outra situação onde esse comando vem a calhar é quando você quer saber se existem espaços no final da linha. O comando |
- | Um ponto importante a saber sobre os comandos de apresentação ('' | + | Um ponto importante a saber sobre os comandos de apresentação (**p**, **n** e **l**) é que eles podem ser combinados com vários dos outros comandos do __ed__ |
< | < | ||
Linha 809: | Linha 791: | ||
</ | </ | ||
- | Nesse exemplo, ao usar '' | + | Nesse exemplo, ao usar **n** e **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 919: | 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 '' | + | 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, | 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, | ||
Linha 931: | Linha 914: | ||
</ | </ | ||
- | Mas o que foi isso? Se você já usou expressões regulares, sabe que os caracteres | + | Mas o que foi isso? Se você já usou expressões regulares, sabe que os caracteres |
- | 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:// | + | 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, | 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, | ||
- | Vejamos um exemplo simples: se eu quiser buscar quaisquer diretivas de pré-processamento do código em '' | + | 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: |
< | < | ||
Linha 947: | Linha 930: | ||
</ | </ | ||
- | Note que aqui pesquisei por qualquer linha que tenha o caractere | + | Note que aqui pesquisei por qualquer linha que tenha o caractere |
< | < | ||
Linha 966: | Linha 949: | ||
</ | </ | ||
- | Se estivéssemos usando as expressões regulares estendidas, poderíamos usar um '' | + | 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 " |
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 " | 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 " | ||
- | Antes que me esqueça de dizer, agora você tem mais um recurso para lidar com os caracteres de controle acidentais: existe a classe | + | Antes que me esqueça de dizer, agora você tem mais um recurso para lidar com os caracteres de controle acidentais: existe a classe |
+ | |||
+ | <note important> | ||
+ | Tenha em mente que a classe **cntrl** abrange caracteres de tabulação, | ||
+ | </ | ||
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, | 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, | ||
- | 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 | + | Vamos voltar a falar sobre comandos que alteram o conteúdo do //buffer//. Já tínhamos visto o comando |
- | Nesse caso, usamos o comando | + | Nesse caso, usamos o comando |
- | 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 ('' | + | 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 |
- | A estrutura do comando | + | A estrutura do comando |
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 992: | Linha 979: | ||
</ | </ | ||
- | O comando | + | O comando |
< | < | ||
Linha 1001: | Linha 988: | ||
</ | </ | ||
- | O que aconteceu aqui? Na linha 22, usei o comando | + | O que aconteceu aqui? Na linha 22, usei o comando |
- | 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 | + | 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 |
< | < | ||
Linha 1011: | Linha 998: | ||
</ | </ | ||
- | "Mas pode isso?" Claro que pode. As linhas que não possuem o termo '' | + | "Mas pode isso?" Claro que pode. As linhas que não possuem o termo '' |
- | Lembrando mais uma vez, a vírgula que antecede o comando, na prática equivale a '' | + | 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 1026: | 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 | + | O comando |
< | < | ||
Linha 1046: | Linha 1033: | ||
</ | </ | ||
- | No comando de substituição demonstrado acima, removemos | + | No comando de substituição demonstrado acima, removemos |
+ | |||
+ | <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 que após a substituição, | + | Note no exemplo acima que após a substituição, |
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 1075: | Linha 1070: | ||
</ | </ | ||
- | Agora, usamos a classe | + | Agora, usamos a classe |
- | No lugar do sufixo | + | No lugar do sufixo |
< | < | ||
Linha 1091: | Linha 1086: | ||
</ | </ | ||
- | Ainda sobre substituições, | + | Ainda sobre substituições, |
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, | 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, | ||
- | Por isso, podemos usar outros caracteres no lugar da barra. Por exemplo, você pode preferir, em alguns casos, usar o caractere //pipe// ('' | + | 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 1886: | 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 | + | Para executar comandos do sistema no __ed__, usamos o comando |
< | < | ||
Linha 1904: | 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. | ||
- | < | + | < |
- | 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__ | ||
</ | </ | ||
- | Se quiser repetir o último comando utilizado, basta usar o atalho | + | Se quiser repetir o último comando utilizado, basta usar o atalho |
< | < | ||
Linha 1918: | Linha 1917: | ||
</ | </ | ||
- | Nesse caso, como houve uma substituição no comando (isto é, do comando fornecido, | + | Nesse caso, como houve uma substituição no comando (isto é, do comando fornecido, |
- | Podemos também usar o sinal de percentual ('' | + | 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. |
< | < | ||
Linha 1935: | Linha 1934: | ||
</ | </ | ||
- | Veja que nesse caso sinal de percentual foi substituído por '' | + | 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, |
Igualmente, poderia estar manipulando o código de um programa interpretado, | Igualmente, poderia estar manipulando o código de um programa interpretado, | ||
Linha 2469: | Linha 2468: | ||
Boa edição! | Boa edição! | ||
+ | |||
+ | ===== História ===== | ||
+ | |||
+ | Bem, agora que você já sabe usar o editor, talvez queira saber um pouco mais sobre sua história. | ||
+ | |||
+ | O editor __ed__ foi um dos primeiros e mais importantes programas do sistema UNIX. Ele foi originalmente criado por Ken Thompson (em 1969), 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. | ||
+ | |||
+ | ===== Padronização ===== | ||
+ | |||
+ | O __ed__ é parte do padrão POSIX. Presente nas seguintes revisões: | ||
+ | |||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | ===== Implementações ===== | ||
+ | |||
+ | Existem diferentes implementações do __ed__. Algumas delas são: | ||
+ | |||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[https:// | ||
+ | |||
+ | Como reflexo da simplicidade deste editor, todas as implementações acima, exceto a do Busybox, aderem totalmente ao proposto no padrão POSIX, e a maioria delas inclui também algumas funcionalidades fora do padrão, como paginadores e atalhos para repetir substituições, |
utils/ed.1735167260.txt.gz · Última modificação: 2024/12/25 19:54 por hrcerq