2

Python で GSM モデムから受信したメッセージを解析しようとしています。

解析する必要があるメッセージがたくさんあります。数時間おきに新しいメッセージを受け取ります。

これは、シリアル オブジェクトを使用してリスト x にデータを読み取った後に受信するデータの例です。

AT+CMGL="ALL"


+CMGL: 1,"REC READ","+918884100421","","13/04/05,08:24:36+22"
here's message one 

+CMGL: 2,"REC READ","+918884100421","","13/04/05,09:40:38+22"
here's message two

+CMGL: 3,"REC READ","+918884100421","","13/04/05,09:41:04+22"
here's message three

+CMGL: 4,"REC READ","+918884100421","","13/04/05,10:04:18+22"
here's message four

+CMGL: 5,"REC READ","+918884100421","","13/04/05,10:04:32+22"
here's message five

.
.
.
.
.

他にもたくさんのメッセージがありますが、ここでは 5 つだけ挙げました。

私の主な意図は、メッセージの内容を抽出することです。たとえば、受信したすべてのメッセージについて、「ここにメッセージ 1 があります」などです。

これが私が今使っているコードです。

def reading():
     print "Reading all the messages stored on SIM card"
     phone.write(b'AT+CMGL="ALL"\r')
     sleeps()
     x=phone.read(10000)
     sleeps()
     print x
     print "Now parsing the message!"
     k="".join(x)
     parse(k)
     k=""
def parse(k):
    m = re.search("\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\r\n(.+)\r\n",k)
    print "6="
    print m.group(6)

phone は、GSM モデムから読み取るために使用しているシリアル オブジェクトです。

ここで m.group(6) は、最初のメッセージ「here's message one」のメッセージ コンテンツをキャプチャします。

最初のメッセージだけでなく、すべてのメッセージの内容と一致させるにはどうすればよいですか。

複数行フラグを設定しようとしましたが、うまくいきませんでした。re.search() の代わりに re.findall() を使用することもありませんでした。

また、re.search によって返される一致オブジェクトは反復可能ではありません。

助けてください。

4

3 に答える 3

3

これに正規表現を使用することは、さまざまな電話の動作のバリエーションを処理できないため、非常に堅牢なソリューションではありません。あなたの例では、応答の形式は

+CMGL: 1,"REC READ","+918884100421","","13/04/05,08:24:36+22"

しかし、他の電話は次のような応答を返します

+CMGL: 1,"REC READ","+31612123738",,"08/12/22,11:37:52+04"

4 番目のパラメーター""と何もない場合の違いに注意してください。27.005をチェックアウトすると、テキスト モードでの応答の構文は次のようになります。

+CMGL: <index>,<stat>,<oa/da>,[<alpha>],[<scts>][,<tooa/toda>,<length>]<CR><LF>
<data><CR><LF>

<alpha>実際にはオプションです。はい、これを考慮した正規表現を書くことはおそらく可能ですが、その場合、land という 2 つの問題に迷い込むことになります。


私がお勧めするのは、応答の適切な解析を行うように切り替えることです。つまり、最初の文字から開始し、予想されるパラメーター形式 (および存在) に応じてチャンクを進めます。電話番号を抽出するための迅速で汚い方法については、この回答を参照してください。以下で説明するアルゴリズムほど堅牢ではありません (たとえばcomma + 2、仮定が多すぎます)。

応答を解析するための絶対正しいアルゴリズムは次のとおりです。

行頭のプレフィックスに一致します (例: +CMGL:)。次に、次のトークンを区別して解析を開始します。

  • 空白' 'または'\t'
  • コンマ','
  • 二重引用符'"'
  • キャリッジリターン'\r'
  • 改行'\n'
  • 任意の非空白スペース非コンマ非二重引用符非 CR 非 LF 文字

パラメータごとに、先頭の空白を無視することから始めます。カンマを取得した場合、パラメーターが存在しませんでした。次のパラメーターの解析に進みます。キャリッジ リターンを取得する場合、次の文字は改行である必要があり、行末に到達します。non-white-space-non... 文字を取得する場合、これは数値パラメータの開始です。このパラメーターに続く空白文字以外のすべての文字を収集します。これに続く唯一の有効な文字は、0 個以上の空白とそれに続くコンマまたはキャリッジ リターンのいずれかでなければなりません。二重引用符文字を取得すると、次の二重引用符文字に進みます。これは文字列の末尾です (文字列に二重引用符文字が含まれている必要がある場合でも、エスケープされますが、エスケープされないため、これは安全で正しいです)\")。これに続く唯一の有効な文字は、0 個以上の空白とそれに続くコンマまたは改行のいずれかでなければなりません。

上記は最初は少し圧倒されるように思えるかもしれませんが、扱い始めると実際にはそれほど複雑ではありません。

于 2013-04-06T10:41:07.800 に答える
1

材料が手元にないので、サンプルを作ります。

'\xef\xbb\xbfAT+CMGL="ALL"\n\n+CMGL: 1,"REC READ","+918884100421","","13/04/05,08:24:36+22"\nhere\'s message one \n\n+CMGL: 2,"REC READ","+918884100421","","13/04/05,09:40:38+22"\nhere\'s message two\n\n+CMGL: 3,"REC READ","+918884100421","","13/04/05,09:41:04+22"\nhere\'s message three\n\n+CMGL: 4,"REC READ","+918884100421","","13/04/05,10:04:18+22"\nhere\'s message four\n\n+CMGL: 5,"REC READ","+918884100421","","13/04/05,10:04:32+22"\nhere\'s message five\n'

これは、を使用した質問から来ています''.join()。そして、正規表現パターンを使用します。使用\r\nする\nサンプルは\n. そして、私は結果を得る。なぜあなたとうまくいかないのかわかりfindallません。

def parse(x):
    res = []
    match = re.finditer("\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\n(.+)\n", x)
    for each in match:
        res.append(each.group(6))
    return res

私が得る結果はです["here's message one ", "here's message two", "here's message three", "here's message four", "here's message five"]finditerイテレータを返し、正常にfindall動作します。

 def parse(x):
        res = []
        match = re.findall("\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\n(.+)\n", x)
        for each in match:
            res.append(each[5])
        return res
于 2013-04-06T10:02:33.053 に答える
0

メッセージが常に改行の場合

(?:[\n\r]+|^)\+CMGL.*?[\n\r]+(.*?)(?=[\n\r]+|$)

グループ 1 には、必要なメッセージが含まれています

于 2013-04-06T08:51:27.737 に答える