Marcado como: tutorial Ativar/desativar aninhamento de comentários | Atalhos do Teclado

  • Fm4lloc 10:32 pm em 20 de July de 2018 Link Permanente | Resposta
    Tags: autocomplete, , deb, , dica, howto, , , terminal, tutorial, ubuntu   

    Habilitar o Autocomplete do Bash 

    Olá, caros leitores!

    Essa é mais uma dica rápida ensinando como habilitar o autocomplete no terminal, aquele usando a tecla [tab].

    O primeiro passo é reinstalar o pacote bash-completion, para o caso de não existir ou você ter estragado alguma coisa, depois copiar o arquivo /etc/bash.bashrc para home nomeando-o direto para .bashrc

    $ sudo apt-get install --reinstall bash-completion
    $ cp /etc/bash.bashrc ~/.bashrc
    

    Após isso, abra o arquivo ~/.bashrc recém copiado com seu editor de textos favorito e encontre o trecho de código correspondente ao abaixo. Descomente as linhas removendo o caractere # (hashtag), só não faça isso para o comentário explicando o que aquilo faz.

    # enable bash completion in interactive shells
    #if ! shopt -oq posix; then
    #  if [ -f /usr/share/bash-completion/bash_completion ]; then
    #    . /usr/share/bash-completion/bash_completion
    #  elif [ -f /etc/bash_completion ]; then
    #    . /etc/bash_completion
    #  fi
    #fi
    

    O Resultado fica assim:

    # enable bash completion in interactive shells
    if ! shopt -oq posix; then
      if [ -f /usr/share/bash-completion/bash_completion ]; then
        . /usr/share/bash-completion/bash_completion
      elif [ -f /etc/bash_completion ]; then
        . /etc/bash_completion
      fi
    fi

    Agora salve o arquivo. O autocomplete já estará funcionando.

     
  • Fm4lloc 4:34 am em 6 de January de 2014 Link Permanente | Resposta
    Tags: artigo, , , exemplos, expressão regular, expression, , , regex, regexp, regular, tutorial   

    Usando expressões regulares em C 

    O presente artigo procura explicar o uso de expressões regulares em conjunto com a linguagem C, desmistificando funções e ensinando a extrair o máximo delas. Adianto que a leitura não é recomendado para elite programmers ou iniciantes, mas pessoas com conhecimento prévio em expressões regulares.

    Definir regras e encontrar padrões demandam códigos extensos e de difícil manutenção. As expressões regulares aparecem é nesse cenário, facilitando e transformando o raciocínio lógico do programador em uma composição de símbolos recheada de significados.

    É normal que programadores novatos ou pessoas que tiveram os primeiros contatos com expressões regulares em Perl, Python ou até mesmo PHP, sejam assombradas quando escultam o termo regex e C na mesma frase. Ocorre que as linguagens destacas anteriormente, com exceção de C, além de serem interpretadas, nasceram prontas para trabalhar com o melhor que concerne a expressões regulares.

     

    O PRIMEIRO CÓDIGO

    O código ulterior compila a expressão e testa se a string casa com um padrão.

    #include <stdio.h>
    #include <regex.h>
    
    /*
     *  Written by: fm4lloc <fm4lloc@gmail.com>
     *
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 2 of the License, or
     *  (at your option) any later version.
     *
     */
    
    int main ()
    {
    	regex_t preg;
    	reg_errcode_t err;
    	const char regex[]  = "^(([^:/?#]+):)?"       \
    						  "(//([^/?#]*))?"        \
    						  "([^?#]*)(\\?([^#]*))?" \
    						  "(#(.*))?"; 
    
    	const char string[]	= "https://fm4lloc.wordpress.com/";
    
    	if ( ( err = regcomp (&preg, regex, REG_EXTENDED|REG_NOSUB) ) != REG_NOERROR)
    		return err;
    
    	if ( (err = regexec (&preg, string, 0 , NULL, 0 ) ) != REG_NOERROR )
    		printf ("No match!");
    	else
    		printf ("Match!");
    
    	regfree (&preg);
    	return 0;
    }
    

    A função regcomp () compila a expressão.
    Esta é a declaração de regcomp ():

    int regcomp(regex_t *preg, const char *regex, int cflags);
    

    *preg é um ponteiro para pattern buffer, ele aponta para o bloco de memória contento o padrão de pesquisa preparado por regcomp () através dos parâmetros fornecidos.

    *regex aponta para um vetor de char contento a expressão regular, enquanto cflags é utilizado para determinar o tipo de compilação através de flags.

    As flags são:

    REG_EXTENDED Usa o padrão POSIX Expressão Regulares Estendidas na interpretação da regex. Quando ela é usada os metacaracteres não precisam ser escapados com a barra invertida (\) para serem identificados. O escape é usado apenas para transformar metacaractere em literal.
    O uso da flag permite isso:

    ^(a.*)$

    Quando omitida, a expressão é tratada através do padrão POSIX Expressões Regulares Básicas. Esse padrão necessita do uso de barras invertidas para a identificação dos metacaracteres.

    ^\\(a.*\\)$

    Recomendo estes links para aprofundar no tema:
    Link1
    Link2

    REG_ICASE Não diferencia letras maiúsculas de minúsculas.
    REG_NOSUB Ignora suporte aos parâmetros nmatch e pmatch usados pela função regexec().Esta flag é fixada quando se deseja apenas testar a entrada de dados com um padrão sem coletar informações adicionais.
    REG_NEWLINE Trata a entrada de dados com várias linhas individualmente.
    Exemplo:

    char string[] = “Olá\nMundo”;
    
    const char regex[] = "^O(.*)$";
    

    Como a entrada possui quebra de linha, a palavra “Olá” e “Mundo” são tratadas individualmente.

    Se omitida, a entrada será tratada como um todo, resultando em “Olá\\nMundo”.

    Voltando a explicação do código, a função regexec() avalia e busca os dados correspondentes a expressão.

    A declaração é:

    int regexec(const regex_t *preg, const char *string,
    		size_t nmatch, regmatch_t pmatch[], int eflags);
    
    *preg Ponteiro para pattern buffer.
    *string Ponteiro para os dados de entrada.
    nmatch Número de matchs, isto é, quantidade casada.
    *pmach[] Ponteiro para um array de regmatch_t.
    eflags
    REG_NOTBOL Ignora o metacaractere circunflexo ‘^’ (inicio de linha).
    REG_NOTEOL Ignora o metacaractere cifrão ‘$’ (final da linha)

    A estrutura de *pmach[] guarda em seus elementos informações sobre o casamento.

    A declaração de regmatch_t em regex.h é:

    typedef struct
    {
    	/* Posição do primeiro byte da sub-string casada
    	 */
    	regoff_t rm_so;
    
    	/* Posição do último byte da sub-string casada
    	 */
    	regoff_t rm_eo;
    } regmatch_t;
    

    A última função presente no código em analise é regfree (), que liberar o pattern buffer.

    Declaração:

    void regfree(regex_t *preg);
    

     

    EXIBINDO AS SUB-STRINGS ENCONTRADAS

    Leia os comentários para entender o código, recomento que compile e faça alterações se achar valido.

    #include <stdio.h>
    #include <stdlib.h>
    #include <regex.h>
    
    /*
     *  Written by: fm4lloc <fm4lloc@gmail.com>
     *
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 3 of the License, or
     *  (at your option) any later version.
     *
     */
    
    int main ()
    {
    	regex_t preg;
    	reg_errcode_t err;
    	regmatch_t *pmatch = NULL;
    	size_t nmatch, i;
    
    	const char regex[]  =	"^(([^:/?#]+):)?"       \
    							"(//([^/?#]*))?"        \
    							"([^?#]*)(\\?([^#]*))?" \
    							"(#(.*))?";
    
    	const char string[]	= "https://fm4lloc.wordpress.com/";
    
    	if( ( err = regcomp (&preg, regex, REG_EXTENDED) ) != REG_NOERROR)
    		return err;
    
    	/*
    	 * Pega o número de matchs e aloca uma lista de regmatch_t.
    	 * ======================================================================
    	 * Soma-se 1 para obter a quantidade total de matchs, pois a
    	 * contagem inicia em zero.
    	 *
    	 * Os elementos contidos em pmatch[0] guardam a posição do primeiro
    	 * e último byte da string, os demais registros correspondem
    	 * aos grupos representados pelo metacaratere (parênteses).
    	 *
    	 * Cada sub-string é capturada por um grupo.
    	 */
    	nmatch = preg.re_nsub + 1;
    
    	/* aloca pmatch */
    	pmatch = (regmatch_t *) malloc (sizeof(regmatch_t) * nmatch);
    
    	if ( (err = regexec (&preg, string, nmatch , pmatch, 0 ) ) != REG_NOERROR )
    	{
    		free (pmatch);
    		return err;
    	}
    
    	/* mostra as sub-strings */
    	for(i = 0; i < nmatch; i++)
    	{
    		printf ("pmatch[%ld] (%d : %d)\t=> %.*s\n",
    			i,
    			pmatch[i].rm_so,pmatch[i].rm_eo,
    			pmatch[i].rm_eo - pmatch[i].rm_so,
    			string + pmatch[i].rm_so);
    	}
    
    	free (pmatch);
    	regfree (&preg);
    	return 0;
    }
    

    Retorno:

    pmatch[0] (0 : 29) => https://fm4lloc.wordpress.com/
    pmatch[1] (0 : 5) => http:
    pmatch[2] (0 : 4) => http
    pmatch[3] (5 : 28) => //fm4lloc.wordpress.com
    pmatch[4] (7 : 28) => fm4lloc.wordpress.com
    pmatch[5] (28 : 29) => /
    pmatch[6] (-1 : -1) =>
    pmatch[7] (-1 : -1) =>
    pmatch[8] (-1 : -1) =>
    pmatch[9] (-1 : -1) =>

    As sub-strings inexistentes recebem (-1, -1).

    Grupos:

    ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
    _12____________3__4__________5_______6__7________8_9____
    

     

    ENCONTRANDO NA STRING TODAS AS OCORRÊNCIAS DO PADRÃO.

    No começo do artigo comentei que Perl nasceu pronto para trabalhar com o melhor que concerne a expressões regulares, não mentei, vou provar no próximo código.

    Para encontrar todas as ocorrências do padrão em Perl:

    #!/usr/bin/perl
    
    use warnings;
    use strict;
    
    my $string	=	"1991/04;".
    				"1992/12;".
    				"1992/05;".
    				"1994/03;".
    				"1995/09;";
    
    for ($string =~ m/([0-9]+)\/([0-9]+)/g)
    {
    	print "$_\n";
    }
    
    Saída
    1991
    04
    1992
    12
    1992
    05
    1994
    03
    1995
    09

    Tudo é simplificado, bastou o uso da opção “g” ao final da expressão. Em C as coisas ficam um pouco mais complexas.

    A mesma ideia em C:

    #include <stdio.h>
    #include <stdlib.h>
    #include <regex.h>
    #include <string.h>
    /*
     *  Written by: fm4lloc <fm4lloc@gmail.com>
     *
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 2 of the License, or
     *  (at your option) any later version.
     *
     */
    
    int main ()
    {
    	regex_t preg;
    	reg_errcode_t err;
    	regmatch_t *pmatch = NULL;
    	size_t	offset = 0, nmatch, i, j;
    
    	const char regex[]  =	"([0-9]+)/([0-9]+)";
    
    	const char string[]	=	"1991/04;" \
    							"1992/12;" \
    							"1992/05;" \
    							"1994/03;" \
    							"1995/09;";
    
    	if( ( err = regcomp (&preg, regex, REG_EXTENDED) ) != REG_NOERROR)
    		return err;
    
    	nmatch = preg.re_nsub + 1;
    	/*
    	 * Define o modo de impressão das sub-strings.
    	 * Só imprime sub-strings do índice zero se não
    	 * existir grupos.
    	 */
    	if (nmatch == 1)
    		j = 0;
    	else
    		j = 1;
    
    	pmatch = (regmatch_t *) malloc (sizeof(regmatch_t) * nmatch);
    
    	/* Tenta casar enquanto não for retornado erro.
    	 *
    	 * O endereço de string é incrementado com offset para evitar
    	 * buscas no mesmo trecho.
    	 */
    	while ((err = regexec (&preg, string + offset,
    		nmatch ,pmatch, 0 )) == REG_NOERROR)
    	{
    		/* mostra as sub-strings.
    		 */
    		for(i = j; i < nmatch; i++)
    			printf ("%.*s\n", pmatch[i].rm_eo - pmatch[i].rm_so,
    				string + pmatch[i].rm_so + offset);
    
    		/* offset: variável auxiliar – usada para pular fragmentos já
    		 * analisados.
    		 *
    		 * Ela recebe o valor referente a posição
    		 * do último byte do pedaço casado anteriormente.
    		 */
    		if (pmatch[0].rm_eo)
    			offset += pmatch[0].rm_eo;
    		else
    			break;
    	}
    
    	free (pmatch);
    	regfree (&preg);
    
    	return 0;
    }
    

    Os códigos escritos no artigo são feitos para facilitar o entendimento, podem ser otimizados ao extremo.

    Exemplo com outras expressões e strings:

    Exemplo 1:

    Regex “^([0-9]+)/([0-9]+);$”
    String “1991/04;\n” \
    “1992/12;\n” \
    “1992/05;\n” \
    “1994/03;\n” \
    “1995/09;\n”;
    regcomp() flags REG_EXTENDED | REG_NEWLINE
    Saída 1991
    04
    1992
    12
    1992
    05
    1994
    03
    1995
    09

    Exemplo 2:

    regex “^[0-9]+/[0-9]+;”
    string “1991/04;” \
    “1992/12;” \
    “1992/05;” \
    “1994/03;” \
    “1995/09;”;
    regcomp() flags REG_EXTENDED
    Saída 1991/04;
    1992/12;
    1992/05;
    1994/03;
    1995/09;

    Exemplo 3:

    regex “^[0-9]+/[0-9]+;”
    string “1991/04;\n” \
    “1992/12;\n” \
    “1992/05;\n” \
    “1994/03;\n” \
    “1995/09;\n”;
    regcomp() flags REG_EXTENDED
    Saída 1991/04;\n

     

    EXIBINDO ERROS

    As funções regcomp () e regexec () retornam um inteiro indicando o ocorrido ao final de cada execução, o retorno é chamado de error code e é declarado no header regex.h assim:

    typedef enum
    {
    #if defined _XOPEN_SOURCE || defined __USE_XOPEN2K
      REG_ENOSYS = -1,	/* This will never happen for this implementation.  */
    #endif
    
      REG_NOERROR = 0,	/* Success.  */
      REG_NOMATCH,		/* Didn't find a match (for regexec).  */
    
      /* POSIX regcomp return error codes.  (In the order listed in the
         standard.)  */
      REG_BADPAT,		/* Invalid pattern.  */
      REG_ECOLLATE,		/* Inalid collating element.  */
      REG_ECTYPE,		/* Invalid character class name.  */
      REG_EESCAPE,		/* Trailing backslash.  */
      REG_ESUBREG,		/* Invalid back reference.  */
      REG_EBRACK,		/* Unmatched left bracket.  */
      REG_EPAREN,		/* Parenthesis imbalance.  */
      REG_EBRACE,		/* Unmatched \{.  */
      REG_BADBR,		/* Invalid contents of \{\}.  */
      REG_ERANGE,		/* Invalid range end.  */
      REG_ESPACE,		/* Ran out of memory.  */
      REG_BADRPT,		/* No preceding re for repetition op.  */
    
      /* Error codes we've added.  */
      REG_EEND,		/* Premature end.  */
      REG_ESIZE,		/* Compiled pattern bigger than 2^16 bytes.  */
      REG_ERPAREN		/* Unmatched ) or \); not returned from regcomp.  */
    } reg_errcode_t;
    

    Pequena rotina que exibe a mensagem correspondente ao error code.

    Observe, regerror () aparece duas vezes na rotina, na primeira ela é chamada para determinar o comprimento da mensagem, enquanto na segunda é invocada com o intuito de copiar a mensagem para *errbuff.

    /*
     *  Written by: fm4lloc <fm4lloc@gmail.com>
     *
     *  This program is free software; you can redistribute it and/or modify
     *  it under the terms of the GNU General Public License as published by
     *  the Free Software Foundation; either version 3 of the License, or
     *  (at your option) any later version.
     *
     */
    
    void c_regerror (reg_errcode_t err, const regex_t *preg)
    {
    	size_t errbuf_size;
    	char *errbuf = NULL;
    
    	errbuf_size  = regerror (err, preg, NULL, 0);
    	errbuf = (char *) calloc (errbuf_size, sizeof(char));
    
    	regerror (err, preg, errbuf, errbuf_size);
    
    	fprintf (stderr, "%s\n", errbuf);
    	free (errbuf);
    }
    

    Declaração de regerror ():

    size_t regerror(int errcode, const regex_t *preg, char *errbuf,
                           size_t errbuf_size);
    
    errcode O error code retornado por regcomp () ou regexec ()
    *preg Aponta para o pattern buffer
    *errbuf Ponteiro para a mensagem de erro
    errbuf_size Número de bytes que serão copiados para *errbuff
     
c
escrever novo post
j
post seguinte/ comentário seguinte
k
post anterior/comentário anterior
r
Resposta
e
Editar
o
mostrar/esconder comentários
t
voltar ao topo
l
vá para login
h
mostrar/ocultar ajuda
shift + esc
Cancelar