Insira novas linhas no fluxo serial antes de gravar no arquivo de texto

1

Eu tenho um leitor de RFID que envia o ID exclusivo da tag RFID para a porta serial do meu linux (framboesa pi) toda vez que obtém uma leitura bem-sucedida. O problema é que ele está enviando sem nenhum caractere de nova linha. Aqui está um exemplo da saída:

root@scalepi:~/scale# ./grabserial -d "/dev/ttyUSB4" -b 9600 
$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#$A0112OKD9990001200005643E#

Eu gostaria de escrever cada entrada em um arquivo de texto com uma nova linha, como esta:

$A0112OKD9990001200005643E#
$A0112OKD9990001200005643E#
$A0112OKD9990001200005643E#

Como você pode ver, cada entrada começa com $ e termina com #

Eu tentei apenas piping o outout para sed usando esta linha para adicionar uma nova linha após o #, mas eu tenho saída zero, porque eu acho sed está procurando por uma nova linha antes de processar os dados:

./grabserial -d "/dev/ttyUSB4" -b 9600 | sed 's/#/#\r\n/g'

Se eu redirecionar a saída para um arquivo e, em seguida, capturar o arquivo, canalizado pelo mesmo comando sed, obtenho o que espero, mas preciso poder gravar os dados em um arquivo nesse formato. pode ler em tempo real.

root@scalepi:~/scale# ./grabserial -d "/dev/ttyUSB4" -b 9600 > /tmp/test2.txt
^C
root@scalepi:~/scale# cat /tmp/test2.txt | sed 's/#/#\r\n/g'
$A0112OKD9990001200005643E#
$A0112OKD9990001200005643E#
$A0112OKD9990001200005643E#
root@scalepi:~/scale# 

Se alguém tiver alguma sugestão para mim, eu agradeceria. Obrigado!

EDITAR - ATUALIZADO

Depois de tentar a solução "tr" abaixo, consegui obter saída em tempo real, mas se eu tentar redirecionar via pipe ou via redirecionamento stdout / stderr, obtive resultados armazenados em buffer de 50-60 linhas de cada vez de obter um resultado de linha por linha.

O comando a seguir me fornecerá a saída em tempo real conforme a porta serial:

./grabserial -d "/dev/ttyUSB4" -b 9600 | tr '#' '\n'

O seguinte comando me dará saída em blocos de 50 ou 60 linhas por vez (não em tempo real):

./grabserial -d "/dev/ttyUSB4" -b 9600 | tr '#' '\n' | sed -u 's/$/#\r/g'

O seguinte comando me dará saída para um arquivo de texto em blocos de 50 ou 60 linhas por vez (não em tempo real):

./grabserial -d "/dev/ttyUSB4" -b 9600 | tr '#' '\n'  > /tmp/test1.txt

FWIW, eu obtenho os mesmos resultados usando cat para ler a porta serial, ao invés de "grabserial".

O comando a seguir me fornece resultados em tempo real:

cat /dev/ttyUSB4 | tr '#' '\n' 

Mas quando tento redirecionar a saída via redirecionamento de canal ou stdout, coloco blocos de dados em buffer no arquivo de texto:

cat /dev/ttyUSB4 | tr '#' '\n' > /tmp/test4.txt
    
por Danny F 23.09.2017 / 06:33

2 respostas

1

Você pode traduzir (ou transliterar) os caracteres # para novas linhas com

 tr '#' '\n'

então

./grabserial -d "/dev/ttyUSB4" -b 9600 | tr '#' '\n'

deve dar a você

$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
$A0112OKD9990001200005643E
            ︙

em tempo real. Se você os sinais de libra e / ou o carro retornar, você pode canalizar o acima em

        … sed 's/$/#\r/'

(usando o fato de que sed (e expressões regulares em geral) use $ para representar o final de uma linha.

Gotcha

Você pode ter um problema que tr buffers sua saída quando essa saída está indo para um pipe ou um arquivo. Talvez a melhor maneira de lidar com isso seja seguir o conselho do αғsнιη para desativar o buffer com stdbuf ; por exemplo,

./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' | sed 's/$/#\r/' > RFIDs.txt

Caso não esteja claro, a opção para stdbuf é minúscula o (oh) e maiúscula L (ell), que diz que a saída padrão deve ser armazenada em buffer.

Linha de fundo (TL; DR) # 1:

Então você deve poder usar

./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' > RFIDs.txt

para obter as entradas sem o # no final ou

./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' | sed 's/$/#/' > RFIDs.txt

para obter as entradas com o # no final, mas sem o \r ou

./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' | sed 's/$/#\r/' > RFIDs.txt

para obter as entradas com o # e o \r no final.

Linha de fundo (TL; DR) # 2:

Você não disse como está terminando o comando. Se você estiver digitando Ctrl + C , que pode estar causando um problema 1 . Se sim, tente:

  • colocando uma das linhas de comando acima no plano de fundo com & , e então
  • quando estiver pronto para sair faça um ps e obtenha o PID do processo grabserial e
  • mate-o com o comando kill .

Linha de fundo (TL; DR) # 3:

Você diz que precisa ler os dados em tempo real, sem entrar em detalhes. Se você tem algum programa / script que é capaz de ler a partir de stdin, tente

./grabserial -d "/dev/ttyUSB4" -b 9600 | stdbuf -oL tr '#' '\n' | sed 's/$/#\r/' | tee RFIDs.txt | your_program 

Isso deve gravar os dados no arquivo de saída enquanto, ao mesmo tempo, o canaliza para o seu programa.

Linha de fundo (TL; DR) # 4:

Se, de fato, cat funcionar tão bem quanto grabserial , você não precisará de nenhum deles. coisas como

stdbuf -oL tr '#' '\n' < /dev/ttyUSB4 | sed 's/$/#\r/' > RFIDs.txt

deve funcionar tão bem.

por 23.09.2017 / 07:21
1

Como sed normalmente armazena em buffer sua saída até que um tamanho de buffer seja preenchido (Provavelmente, 4K bytes), você poderia usar -u como opção específica do GNU para descompactar a saída.

Por favor, veja Desactivar a memória intermédia no pipe e relacionados responder por sed .

    
por 23.09.2017 / 08:11