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 [2025/01/09 22:00] – [Mais comandos de visualização] detalhamento de caracteres não imprimíveis hrcerq | utils:ed [2025/01/19 13:26] (atual) – [Uma nota sobre alertas] transformado em nota hrcerq | ||
---|---|---|---|
Linha 196: | 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 204: | 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 218: | 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 226: | 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 238: | 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 ===== | ||
Linha 277: | Linha 277: | ||
" | " | ||
- | 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 **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. | ||
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. | ||
+ | </ | ||
===== Indo e voltando ===== | ===== Indo e voltando ===== | ||
Linha 900: | 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 912: | 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 928: | 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 947: | 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 973: | Linha 979: | ||
</ | </ | ||
- | O comando | + | O comando |
< | < | ||
Linha 982: | 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 992: | 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 1007: | 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 1027: | 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 1056: | Linha 1070: | ||
</ | </ | ||
- | Agora, usamos a classe | + | Agora, usamos a classe |
- | No lugar do sufixo | + | No lugar do sufixo |
< | < | ||
Linha 1072: | 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 1867: | 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 1885: | 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 1899: | 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 1916: | 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, |
utils/ed.1736470839.txt.gz · Última modificação: 2025/01/09 22:00 por hrcerq