Conheça estes 7 motivos para abandonar o comando grep e passar a usar o ack.

Tecnicamente, o ack foi projetado como ferramenta de busca dentro de arquivos texto — tendo como público-alvo os programadores.
Entre estes, o utilitário é mais eficiente do que o comando grep.
Neste texto, vou mostrar algumas vantagens de uso do ack e como instalar a ferramenta no Linux (caso ela já não esteja instalada aí).
Entre as vantagens de usar o ack — para fazer pesquisa dentro do código fonte — a documentação oficial cita:

  1. É rápido — por que se restringe a strings que “façam sentido” retornar. As expressões regulares em Perl tem alto índice de otimização.
  2. É portável — por ser escrito em Perl e não ter outras dependências além do Perl 5, pode rodar no Windows, MAC, UNIX e nos vários sabores do BSD e do Linux.
  3. Ignora automaticamente diretórios irrelevantes para a sua busca — a recursividade é seu comportamento padrão, mas ele ignora arquivos .git, .svn e diretórios CVS e VCS. Lógico que você pode mudar isto manualmente.
    Como exemplo da praticidade, a documentação compara os dois comandos de busca, a seguir, que tem resultados semelhantes:

    grep pattern $(find . -type f | grep -v '\.git')
    

    ou

    ack pattern
    

    Qual você prefere?

  4. Melhores resultados — como ele prioriza arquivos de código fonte, você obtém menos resultados irrelevantes. Ele pula até arquivos de backup.
  5. Separa fácil os arquivos — para quem tem um projeto envolvendo mais de uma linguagem de programação (muito comum entre web developers).
    É fácil adicionar –python, para restringir as buscas dentro de arquivos da linguagem Python, ou –nohtml evitar arquivos HTML.

    O ack tem detecção de tipos de arquivos, muito além da leitura da extensão do nome.

    Veja outra comparação entre comandos grep e ack, para realizar buscas dentro de arquivos Perl:

    grep pattern $(find . -name '*.pl' -or -name '*.pm' -or -name '*.pod' | grep -v .git)
    
    ack --perl pattern 
    

    Novamente, qual dos dois comandos, acima, você prefere usar?
    Note que o sucesso do grep, no primeiro exemplo, depende do uso do comando find (leia mais sobre ele aqui). O ack é visivelmente mais eficiente, neste caso.

  6. Listas de arquivos — podem ser criadas, antes mesmo de qualquer busca.
    Esta utilidade vai agradar até quem não é programador. Com o comando, abaixo, o ack relaciona todos os arquivos da linguagem PHP, em um diretório, recursivamente:

    ack -f --php
    

    Você gastaria um pouco mais de seus dedos para realizar esta tarefa com o find…

  7. O ack tem highlighting, que permite realçar palavras-chave nos resultados das buscas.

linux terminal ack command
Por fim, A palavra “ack” é menor do que “grep”, o que te poupa alguns preciosos milésimos de segundos na digitação a cada vez que precisar realizar uma busca.

Como instalar o ack no sistema

O ack está disponível nos repositórios das principais distribuições (se não todas) Linux e UNIX (BSD).
Infelizmente, no momento em que escrevo este texto, ele ainda não faz parte do conjunto de programas utilitários padrão, que já “estão lá”, logo após a instalação.
Contudo, ele é super fácil de instalar.
Quem usa o Debian, pode usar o apt, para fazer o trabalho:

sudo apt update
sudo apt install ack

No Ubuntu 16.04 LTS, o nome do pacote (transitório) é ack-grep. Nas futuras atualizações ele deve ser renomeado para apenas “ack”.
O pessoal do Fedora, pode instalar com o dnf:

sudo dnf install ack

No FreeBSD, use os ports e instale o pacote p5-ack.
Leia outros textos sobre o assunto, tocando ou clicando na tag ack, para conhecer melhor a ferramenta.
Além disto, não esqueça de compartilhar o texto nas redes sociais. 😉

Referências

https://beyondgrep.com/.
http://www.activestate.com/blog/2016/12/grep-losing-its-grip.

Como manipular valores de data e hora como números no MySQL

Transformar strings contendo valores temporais (de data e/ou hora) pode ser útil quando se deseja realizar operações aritméticas, envolvendo-os. Os valores podem ser convertidos de volta para data e/ou hora, com relativa facilidade.
O processo consiste, basicamente em adicionar o valor zero ou usar o valor temporal em um contexto numérico — o MySQL irá entender que aquele valor é um número.
Veja um exemplo:

SELECT CURRENT_DATE() AS Hoje, CURRENT_DATE()+0 AS "Hoje, como núm.";
+------------+------------------+
| Hoje       | Hoje, como núm.  |
+------------+------------------+
| 2015-07-14 |         20150714 |
+------------+------------------+

CURRENT_DATE() é a função responsável por retornar a data atual. Como você pode ver, no exemplo acima, ao adicionar 0 (zero), o valor passou de data para número.
Na condição de valor numérico, é possível realizar todas as operações aritméticas e, em seguida, voltar (nem sempre…) a valor temporal.
Veja outro exemplo:

SELECT DATE(DataCadastroCliente) AS Cadastro, DATE(DataCadastroCliente)+0 AS "Número", YEAR(DataCadastroCliente)+1 AS "Ano +1" FROM CadastroClientes LIMIT 10;
+------------+----------+--------+
| Cadastro   | Número   | Ano +1 |
+------------+----------+--------+
| 2016-03-29 | 20160329 |   2017 |
| 2015-06-20 | 20150620 |   2016 |
| 2013-03-29 | 20130329 |   2014 |
| 2015-11-29 | 20151129 |   2016 |
| 2016-06-11 | 20160611 |   2017 |
| 2014-06-14 | 20140614 |   2015 |
| 2015-08-31 | 20150831 |   2016 |
| 2012-08-28 | 20120828 |   2013 |
| 2013-05-29 | 20130529 |   2014 |
| 2013-06-03 | 20130603 |   2014 |
+------------+----------+--------+

mysql-convert-datetime-to-number
Fique atento.
Ao adicionar 0 (ou qualquer outro valor numérico) a um valor temporal, este deixa de ter valor temporal e passa a ser uma simples string numérica.
Essencialmente, você deve esperar, como resultado, uma string sem os delimitadores de data.
Mas apenas o primeiro componente da data ou da hora será interpretado como numérico, durante a conversão. Veja por si só:

SELECT '2016-01-01'+0, '2016-01-01 15:45:25'+0, '15:45:25'+0;
+----------------+-------------------------+--------------+
| '2016-01-01'+0 | '2016-01-01 15:45:25'+0 | '15:45:25'+0 |
+----------------+-------------------------+--------------+
|           2016 |                    2016 |           15 |
+----------------+-------------------------+--------------+

Para resolver isto, use as funções SEC_TO_TIME() e TIME_TO_SEC().

Como decompor ou combinar strings no MySQL

Saiba como quebrar ou separar partes de uma cadeia de caracteres para obter uma substring ou como combinar mais de uma string para obter uma cadeia maior.
Partes deste assunto, já foram abordadas em outros artigos no site — portanto, se quiser saber um pouco mais sobre algum quesito, clique nos links correspondentes, ao longo do texto.
Outumn trees over lake and mysql logo
A solução para separar trechos de uma cadeia de caracteres é usar uma função de extração de substrings.
Para obter o efeito contrário, use a função CONCAT(). Com esta função, é possível juntar cadeias de caracteres e criar novas formatações para diversos tipos de dados.

Funções para extração de caracteres ou strings no MySQL

A versão 5.7 do MySqL tem mais de 50 funções para lidar com strings.
Ao aprender a lidar com algumas, você estará apto(a) a lidar com todas.
Nos primeiros exemplos deste post, vou mostrar o funcionamento de 3, destas funções: LEFT(), MID() e RIGHT().
Elas servem para extrair substrings de uma cadeia de caracteres da parte à esquerda, do meio e da direita, respectivamente.
Neste primeiro exemplo, vou mostrar como retirar 2 caracteres destas partes da relação de cidades, da tabela ClientesCidades.

SELECT CidadeCliente, LEFT(CidadeCliente, 2) AS "Primeira parte", MID(CidadeCliente, 3, 2) AS "Parte do meio", RIGHT(CidadeCliente, 2) AS "Última parte" FROM ClientesCidades LIMIT 5;
+---------------+----------------+---------------+---------------+
| CidadeCliente | Primeira parte | Parte do meio | Última parte  |
+---------------+----------------+---------------+---------------+
| Buti          | Bu             | ti            | ti            |
| Whitehorse    | Wh             | it            | se            |
| Bertiolo      | Be             | rt            | lo            |
| Exeter        | Ex             | et            | er            |
| Fortune       | Fo             | rt            | ne            |
+---------------+----------------+---------------+---------------+
5 rows in set (0.00 sec)

A função LEFT() retorna o número especificado e caracteres de dentro de uma string. Veja um outro exemplo:

SELECT LEFT('GNU/Linux',3);
+----------------------+
| LEFT('GNU/Linux', 3) |
+----------------------+
| GNU                  |
+----------------------+
1 row in set (0.00 sec)

Com a função RIGHT(), tudo funciona do mesmo jeito. Só que na direção inversa:

SELECT RIGHT('GNU/Linux', 5);
+-----------------------+
| RIGHT('GNU/Linux', 5) |
+-----------------------+
| Linux                 |
+-----------------------+
1 row in set (0.00 sec)

A função MID() é sinônima de SUBSTRING(). Ela pede que você informe em que posição, no meio da string, a contagem deve começar:

SELECT MID('Debian GNU/Linux', 8, 3);

A declaração pede para “retirar 3 caracteres, a partir da 8a. posição”:

+-------------------------------+
| MID('Debian GNU/Linux', 8, 3) |
+-------------------------------+
| GNU                           |
+-------------------------------+
1 row in set (0.00 sec)

Mysql string functions
Clique para ampliar.

A função SUBSTR() tem funcionamento semelhante, de acordo com a documentação do MySQL (veja link ao final do texto).
A função LEFT() pode ser usada para encontrar todos os nomes, dentro de uma tabela, que comecem com uma determinada letra do alfabeto:

SELECT LEFT(nomeCliente,6) FROM ClientesCidades WHERE LEFT(nomeCliente,1)="W";
+---------------------+
| LEFT(nomeCliente,6) |
+---------------------+
| Winter              |
| Willow              |
| Wilma               |
| Willow              |
| Willow              |
| Wyomin              |
| Willa               |
| Wynne               |
+---------------------+
8 rows in set (0.00 sec)

Veja como obter uma relação de nomes de clientes cujos nomes começam com W, X, Y ou Z (as últimas letras do alfabeto em inglês), em ordem alfabética:

SELECT nomeCliente AS "Clientes de W a Z" FROM ClientesCidades WHERE LEFT(nomeCliente,1)>="W" ORDER BY nomeCliente;
+-------------------+
| Clientes de W a Z |
+-------------------+
| Willa Kerr        |
| Willow Graham     |
| Willow Mitchell   |
| Willow Simmons    |
| Wilma Hill        |
| Winter Fischer    |
| Wynne Bauer       |
| Wyoming Graham    |
| Xantha Wise       |
| Xyla Dennis       |
| Yen Espinoza      |
| Yetta Wood        |
| Yoshi Nguyen      |
| Yvonne Wilcox     |
| Zelenia Brady     |
| Zelenia Moss      |
| Zenia Carr        |
| Zephr Webb        |
| Zia Fernandez     |
+-------------------+
19 rows in set (0.00 sec)

Você pode usar a função CONCAT(), para construir novas strings, usando os nomes dos clientes:

SELECT CONCAT("A Cliente ",nomeCliente, " mora em ",cidadeCliente) AS "Clientes de Y a Z" FROM ClientesCidades WHERE LEFT(nomeCliente,1)>="Y" ORDER BY nomeCliente;

Veja o meu resultado:

+------------------------------------------------+
| Clientes de Y a Z                              |
+------------------------------------------------+
| A Cliente Yen Espinoza mora em Pramaggiore     |
| A Cliente Yetta Wood mora em Doues             |
| A Cliente Yoshi Nguyen mora em Daiano          |
| A Cliente Yvonne Wilcox mora em Sherbrooke     |
| A Cliente Zelenia Brady mora em Modena         |
| A Cliente Zelenia Moss mora em Elx             |
| A Cliente Zenia Carr mora em Wernigerode       |
| A Cliente Zephr Webb mora em Recanati          |
| A Cliente Zia Fernandez mora em Market Drayton |
+------------------------------------------------+
9 rows in set (0.00 sec)

Como você pode ver, dá pra brincar bastante com as funções de manipulação de strings. Faça as suas experiências!
Você pode usar a função CONCAT(), para alterar os valores de uma coluna.
No exemplo, abaixo, acrescentamos a string “_abc” aos nomes dos clientes da tabela ClientesCidades:

UPDATE ClientesCidades SET NomeCliente = CONCAT(NomeCliente,"_abc");
SELECT NomeCliente FROM ClientesCidades LIMIT 5;
+---------------------+
| NomeCliente         |
+---------------------+
| Dara Chase_abc      |
| Hanae Kane_abc      |
| Jaden Moon_abc      |
| Cathleen Harvey_abc |
| Marcia Cole_abc     |
+---------------------+
5 rows in set (0.00 sec)

Para desfazer esta bagunça, você pode usar a função LENGTH() para posicionar a função LEFT() antes destes 4 caracteres e gravar o resultado:

UPDATE ClientesCidades SET NomeCliente = LEFT(NomeCliente, LENGTH(NomeCliente)-4);

E veja como tudo volta ao normal:

SELECT NomeCliente FROM ClientesCidades LIMIT 5;
+-----------------+
| NomeCliente     |
+-----------------+
| Dara Chase      |
| Hanae Kane      |
| Jaden Moon      |
| Cathleen Harvey |
| Marcia Cole     |
+-----------------+
5 rows in set (0.00 sec)

Referências:

Como combinar nomes de colunas com a função CONCAT() do MySQL

No MySQL, a função CONCAT tem a função de concatenar strings, ou seja, juntar cadeias de caracteres com o objetivo de formar novos nomes para as suas colunas e enriquecer a apresentação dos dados da sua tabela.
Capa do tutorial da função concat no MySQL
No artigo Como nomear as colunas das tabelas no MySQL, mostrei como melhorar a apresentação das colunas ao exibir as informações da sua tabela — recomendo dar uma olhada.
Neste texto, vou mostrar como usar a função CONCAT() para juntar valores alfanuméricos e formar novos nomes de campos em uma tabela.

Como usar a função CONCAT, do MySQL, para juntar cadeias de caracteres

Em conjunto com o alias (ou AS) é possível criar nomes mais interessantes e significativos para as colunas exibidas de uma tabela.
Veja a sintaxe da função CONCAT():
CONCAT(string1,string2,string3...);
Pode ficar mais fácil de entender, dentro de um exemplo prático.
Veja como concatenar as strings “just”, “in” e “case”:
CONCAT("just","in","case");
O resultado da operação acima é justincase. Foi fácil?
Tome, como exemplo, a seguinte tabela:

SELECT * FROM ClientesCidades WHERE Id<10;
+----+-----------------+--------------+------------------+-------------+
| id | NomeCliente     | IdadeCliente | CidadeCliente    | CredCliente |
+----+-----------------+--------------+------------------+-------------+
|  1 | Dara Chase      |           40 | Buti             |          21 |
|  2 | Hanae Kane      |           26 | Whitehorse       |          28 |
|  3 | Jaden Moon      |           29 | Bertiolo         |          17 |
|  4 | Cathleen Harvey |           39 | Exeter           |          12 |
|  5 | Marcia Cole     |           49 | Fortune          |          13 |
|  6 | Winter Fischer  |           47 | Girifalco        |          53 |
|  7 | Irene Mann      |           48 | Rocca San Felice |          78 |
|  8 | Yetta Wood      |           46 | Doues            |          89 |
|  9 | Alfreda Church  |           38 | Tarnów           |          96 |
+----+-----------------+--------------+------------------+-------------+
9 rows in set (0.00 sec)

Vamos usar o CONCAT() e o AS para exibir a idade de cada cliente entre colchetes e ao lado de cada nome:

SELECT Id AS Ordem, CONCAT(NomeCliente,'[',IdadeCliente,']') AS 'Cliente[Idade]' FROM ClientesCidades WHERE Id<10;
+-------+---------------------+
| Ordem | Cliente[Idade]       |
+-------+---------------------+
|     1 | Dara Chase[40]      |
|     2 | Hanae Kane[26]      |
|     3 | Jaden Moon[29]      |
|     4 | Cathleen Harvey[39] |
|     5 | Marcia Cole[49]     |
|     6 | Winter Fischer[47]  |
|     7 | Irene Mann[48]      |
|     8 | Yetta Wood[46]      |
|     9 | Alfreda Church[38]  |
+-------+---------------------+
9 rows in set (0.00 sec)

Vamos elaborar melhor este exemplo, incluindo informações sobre sua cidade e o valor de seu crédito:

SELECT CONCAT(NomeCliente,', tem ',IdadeCliente,' anos de idade. Mora em ',CidadeCliente,' e possui R$ ',CredCliente,' em créditos.') AS 'Maiores correntistas' FROM ClientesCidades WHERE CredCliente > 97;
+------------------------------------------------------------------------------------+
| Maiores correntistas                                                               |
+------------------------------------------------------------------------------------+
| Cynthia Levy, tem 21 anos de idade. Mora em Pukekohe e possui R$ 99 em créditos.   |
| Tasha Walters, tem 19 anos de idade. Mora em Goutroux e possui R$ 98 em créditos.  |
| Zelenia Moss, tem 18 anos de idade. Mora em Elx e possui R$ 99 em créditos.        |
+------------------------------------------------------------------------------------+
3 rows in set (0.00 sec)

Experimente outras combinações, para obter resultados diferentes e fixar melhor o aprendizado.
Se quiser aprofundar o aprendizado, use caixa de busca, no topo deste site, para encontrar outros exemplos MySQL.
Divirta-se!