Formatando saída com Awk e regex

1

Eu tenho ~ 20 arquivos em todas as 300 linhas, preenchidos por dados formatados assim:

62640 usec, 3500 usec
1640 usec, 480 usec
360 usec, 520 usec
1200 usec, 500 usec
340 usec, 520 usec

e eu quero transformar isso em código Arduino, no formato

delayMicroseconds(62640);
pulseIR(3500);
delayMicroseconds(1640);
pulseIR(480);
delayMicroseconds(360);
pulseIR(520);
delayMicroseconds(1200);
pulseIR(500);
delayMicroseconds(340);
pulseIR(520);

e assim por diante, onde o número na função delayMicroseconds () é o primeiro número em cada linha, e o número em pulseIR () é o segundo número em cada linha.

Alguma ideia? Eu sinto que isso deveria ser possível no awk.

    
por Craig Smith 08.10.2018 / 00:14

4 respostas

11

Não há necessidade de qualquer regex aqui - apenas printf para formatar os campos em uma string:

$ awk '{printf("delayMicroseconds(%d);\npulseIR(%d);\n", $1, $3)}' file
delayMicroseconds(62640);
pulseIR(3500);
delayMicroseconds(1640);
pulseIR(480);
delayMicroseconds(360);
pulseIR(520);
delayMicroseconds(1200);
pulseIR(500);
delayMicroseconds(340);
pulseIR(520);
    
por 08.10.2018 / 00:18
2

você pode tentar isto:

    #!/bin/bash
    cat file |sed '1d' | while IFS= read line; do

    n1=$(echo $line | awk '{print $1}')
    n2=$(echo $line | awk '{print $3}') 

    echo "
    delayMicroseconds($n1);
    pulseIR($n2);
    "
    done

delayMicroseconds(62640);
pulseIR(3500);
delayMicroseconds(1640);
pulseIR(480);
delayMicroseconds(360);
pulseIR(520);
delayMicroseconds(1200);
pulseIR(500);
delayMicroseconds(340);
pulseIR(520);

Como alternativa, você pode tentar perl da seguinte maneira:

perl -pe 's/(\d+)[\D]+(\d+)[\D]+/delayMicroseconds($1);\npulseIR($2);\n/' file
delayMicroseconds(62640);
pulseIR(3500);
delayMicroseconds(1640);
pulseIR(480);
delayMicroseconds(360);
pulseIR(520);
delayMicroseconds(1200);
pulseIR(500);
delayMicroseconds(340);
pulseIR(520);
    
por 08.10.2018 / 00:17
2

Com o GNU sed:

$ sed -Ee 's/([0-9]+) usec, ([0-9]+) usec.*/delayMicroseconds();\npulseIR();/' < data 
delayMicroseconds(62640);
pulseIR(3500);
...

-E informa sed para usar expressões regulares estendidas (*) , o comando s/pattern/replacement/ executa uma operação de substituição de pesquisa sobre a linha atual ( sed repete as instruções dadas para cada linha de entrada).

O padrão é ([0-9]+) usec, ([0-9]+) usec.* , em que [0-9] significa qualquer dígito, + qualquer número do "átomo" anterior e (...) salva ("capturas") o que foi correspondido. Portanto, ([0-9]+) significa qualquer número de qualquer dígito e salva o resultado. As letras são correspondidas como estão e o% final .* corresponde a qualquer número de caracteres, apenas para comer qualquer lixo possível no final da linha.

Na substituição, e são substituídos pelo conteúdo salvo dos grupos (...) (mas os parênteses são literais aqui) e \n significa os caracteres da nova linha (isso pode não funcionar em todos os sed s).

(*) Veja Por que minha expressão regular funciona em X, mas não em Y? para a diferença entre os diferentes tipos de regex. Além disso, há vários tutoriais para sed online. Sugiro encontrar um ou dois e brincar com ele, pelo menos para se familiarizar com o comando s/// .

    
por 08.10.2018 / 00:22
1

Usando o GNU awk:

awk -v RS=' usec[,\n] ?' '{print (NR%2?"delayMicroseconds":"pulseIR")"("$0")"}' file

Isso está usando a string usec como separador de registro. Isso permite capturar cada número como um registro diferente e, portanto, o comando print exibe alternativamente a sequência de 2 com o número desejado.

    
por 08.10.2018 / 13:26