VidaGeek.net

Linux, Open-source, Programação e Produtividade

Awk & Sed

Agora que além de aprendiz de cientista da computação, eu virei Engenheiro de Informática e Redes em treinamento, tenho aulas de Administração de Sistemas aqui em ESISAR.

Um dos exercícios de Trabalho Prático (Exercício Programa + Professor para quem é do IME) era escrever um script que listasse todos os usuários em /etc/passwd.

Rapidamente me lembrei de “Cadu punhos de aço” e dei minha resposta usando sed, entretanto, o que você vê abaixo é uma versão melhorada e corrigida por Tiago Peczenyj (obrigado thiago):

root@linux# sed -nr ‘/^([^:]+):x:([^0][0-9]{2,}).*$/{s//\2 - \1/;p}’ /etc/passwd

Feliz com a minha resposta, o professor mostrou o mesmo comando com awk:

root@linux# awk -F’:’ ‘{ if ($3 > 100) printf “%s - %s \n”,$3,$1}’ /etc/passwd

(nos comentários existem versões com melhorias :-)

Achei fantástico como awk pode ser mais verboso. Alguém ai conhece um ou outro e pode mostrar umas dicas?

Para quem quer aprender um dos dois, ficam aqui os links:

Sed - Un Introduction Tutorial by Bruce Brannet

Awk - A tutorial

Posts Relacionados:

  • No related posts
  • Acompanhe-nos por RSS, por Email ou via Twitter.
    Veja como ter um desconto no Dreamhost: um excelente servidor web.

  • 4 Comments
  • Filed under: Linux
  • Como exibir branch atual do git

    Umas das coisas legais que bash tem é uma variável que define como deve ser o prompt da linha de comando. Essa variavel de ambiente se chama PS1. Um dos usos mais incríveis que já vi dela foi o de mostrar em qual branch do git você está (e não mostrar nada quando você não está em um repositório).

    Isso é a diferença entre

    terminal que não mostra o branch

    e isso

    terminal que mostra o branch

    Não sei quanto a vocês, mas eu realmente fico mais feliz com a segunda forma.

    A minha variável PS1 é configurada da seguinte forma (mac - ~/.bash_profile - linux - ~/.bashrc):

    export PS1="\[\033[38m\]\u\[\033[32m\] \w \[\033[31m\]\`git \\
    branch 2>/dev/null | grep \"^\*\" | \\
    sed -r \"s/\*\ (.*)/ \(\1\)/\"\`\[\033[37m\]$\[\033[00m\] "
    

    Impossível de ler, correto? Vou quebrar em mais linhas para facilitar a vida.

    PS1="\[\033[38m\]\u";
    PS1="$PS1\[\033[32m\] \w";
    PS1="$PS1\[\033[31m\]";
    PS1="$PS1\`git branch 2>/dev/null | grep \"^\*\" | \\
                               sed -r \"s/\*\ (.*)/ \(\1\)/\"\`";
    export PS1="$PS1\[\033[37m\]$\[\033[00m\]";
    

    Não testei, mas deve ter o mesmo efeito. Explicando um pouco da mágica:

    1. Essa sequência bizarra de caracteres (\[\033[38m\]) é a forma de definir que o que virá depois será impresso em branco, num terminal que permite coloração (o que realmente define a cor é o 38m. O resto é apenas a forma de indicar a mudança de cor). “\u”, na PS1, significa o usuário atual.
    2. A próxima sequência de caracteres bizarros troca a cor para verde. “\w”, na PS1, é o seu path atual.
    3. Troca a cor para vermelho.
    4. Extrai o nome do branch (sendo executado em uma subshell. Para isso que servem os \`).

      1. git branch 2>/dev/null: Imprime todos os branches do repositório onde você se encontra. Caso ocorra algum erro, a mensagem de erro será enviada para /dev/null, vulgo limbo (por isso nada será impresso nos outros diretórios).
      2. grep “^\*”: Me dá todas as linhas começadas por * .
      3. sed -r \”s/\*\ (.*)/ \(\1\)/\”: Novamente o grande monstro sed salva o dia. A regex que está ali pega o que vêm depois do espaço que está depois do * e imprime com parenteses em volta.
    5. Muda a cor para branco, imprime $ (apenas para marcar o fim do prompt) e para de brincar com as cores do terminal, devolvendo o controle à shell.

    A versão anterior que eu usava da PS1 usava ruby pra fazer essa mágica toda, mas dessa forma não depende mais do ruby instalado na máquina.

    Posts Relacionados:

  • Como desfazer commits na branch errada no Git
  • Git Workflow
  • Auto refresh no eclipse
  • Como migrar de SVN para GIT
  • Como descobrir todos que commitaram em um repositório SVN
  • Ambiente aberto de Xadrez Online
  • Truques do Bash
  • Acompanhe-nos por RSS, por Email ou via Twitter.
    Veja como ter um desconto no Dreamhost: um excelente servidor web.

  • 0 Comments
  • Filed under: Dicas, Programacao
  • Recentemente escrevi um post sobre como migrar seu repositório svn para o git. Em um dos passos falo pra você criar uma lista de mapeamento dos seus usuários do svn para os do git. O único problema disso é descobrir quem são eles. Aqui vai um one-liner de bash que resolve isso :)

    
    svn log | grep "^r[0-9]" | \\
    sed -E "s/^.*\|(.*)\|.*\|.*$/\1/" | \\
    sort | uniq > seu_arquivo_com_os_usuarios
    

    Explicação da bizarrice acima:

    1. svn log: Exibe todo o log de commits feitos naquele repositório.
    2. grep “^r[0-9]“: Pega todas as linhas iniciadas com r seguido por um número (header de cada commit do svn)
    3. sed -E “s/^.*\|(.*)\|.*\|.*$/\1/”: Roda o monstro chamado sed em modo estendido e captura o nome dos usuários (conte o número de pipes)
    4. sort: Ordena a lista com os usuários que comitaram.
    5. uniq: elimina todas as duplicatas deixando apenas uma cópia de cada usuário (só funciona em listas ordenadas. Por isso o sort anterior).

    Tentei fazer usando o comando cut no lugar do sed, mas o cut desistia no meio do caminho por causa de caracteres estranhos.

    Posts Relacionados:

  • Como migrar de SVN para GIT
  • Como remover os malditos .svn
  • Truques do Bash
  • Como descobrir o real encoding de um arquivo em java
  • Git Workflow
  • Configuração de caminhos no LaTeX
  • Google em Inglês
  • Acompanhe-nos por RSS, por Email ou via Twitter.
    Veja como ter um desconto no Dreamhost: um excelente servidor web.

  • 1 Comment
  • Filed under: Dicas, Linux, Programacao