0
0

More than 1 year has passed since last update.

python でバイト文字列を正規表現でパース

Last updated at Posted at 2022-08-10

以下のような、csv に似たデータをシリアル通信で受け取る。

b'@-114,6,6 304 451 10097 505\r\n'

末尾は CRLF。頭に@がついて、7つのフィールド間のデミリタはカンマまたはスペース。

環境

  • Python 3.9.2
  • RaspberryPi OS Raspbian GNU/Linux 11 \n \l

作戦

バイト列としてシリアル通信で受信する。

以下のことに注意して処理する。

  • readline() で一行受け取るので \r\n がくっついてくる
  • 数値は符号付き整数
  • 4,5,6番目のフィールドは小数点以下1位の固定小数で "257" と送られてきたのは "25.7"を意味している
  • 7つのフィールド間のデミリタは1バイトのカンマまたは1バイトのスペース
  • 頭に @ がついていることをチェック
  • 通信エラーで異常文字列が来ること前提

正規表現を使う

↓↓↓↓↓↓↓ あなたの記事の内容

───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容

  result=( re.match( rb'^@([-0-9]*)'    # 行頭の@に続く符号付整数
                      +b',([-0-9]*)'    # ,で区切られた符号付き整数
                      +b',([-0-9]*)'    # ,で区切られた符号付き整数
                      +b'[ ,]([-0-9]*)' # ,あるいはスペースで区切られた符号付き整数
                      +b'[ ,]([-0-9]*)' # ,あるいはスペースで区切られた符号付き固定小数
                      +b'[ ,]([-0-9]*)' # ,あるいはスペースで区切られた符号付き固定小数
                      +b'[ ,]([-0-9]*)' # ,あるいはスペースで区切られた符号付き整数
            , onerecord))

パースした値を取り出す

↓↓↓↓↓↓↓ あなたの記事の内容

───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
result.group(n)

としてn番目のフィールドがバイト文字列で取り出せる。

取り出した値の変換

これを utf8 文字列にするには

↓↓↓↓↓↓↓ あなたの記事の内容

───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
result.group(n).decode('utf-8')

整数型にするには

↓↓↓↓↓↓↓ あなたの記事の内容

───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
int(result.group(n))

固定小数フィールドを float にするには
↓↓↓↓↓↓↓ あなたの記事の内容

───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容
float(result.group(n))/10

サンプルプログラム

↓↓↓↓↓↓↓ あなたの記事の内容

───────
```python
↑↑↑↑↑↑↑ 編集リクエストの内容

import serial
import pymysql.cursors
import time
import re

ser = serial.Serial("/dev/ttyS0",115200)

while 1:

  oneline = ser.readline()
  result=( re.match( rb'^@([-0-9]*)'
                      +b',([-0-9]*)'
                      +b'[ ,]([-0-9]*)'
                      +b'[ ,]([-0-9]*)'
                      +b'[ ,]([-0-9]*)'
                      +b'[ ,]([-0-9]*)'
                      +b'[ ,]([-0-9]*)'
            , onerecord))

  rssi=int(result.group(1))
  node1=int(result.group(2))
  node2=int(result.group(3))
  temp=float(result.group(4))/10
  humi=float(result.group(5))/10
  pressure=float(result.group(6))/10
  co2=int(result.group(7))

  db=pymysql.connect(host="localhost", user="hogehoge", password="hagehage" , cursorclass=pymysql.cursors.DictCursor)
  cursor=db.cursor()
  cursor.execute("USE hokan")
  db.commit()
  sql=('insert into hokandata (recvtime,node,rssi,recv,temp,humi,pressure,co2) values (now(),"%s","%s","%s","%s","%s","%s","%s");')
  cursor.execute(sql,(node1,rssi,result2,temp,humi,pressure,co2))
  db.commit()
  db.close()

temp=float(result.group(4))/10

temp=float(result.group(4).decode('utf-8'))/10

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0