2013-04-06 2 views
2

파이썬에서 GSM 모뎀으로부터받은 메시지를 구문 분석하려고합니다.파이썬에서 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 개를 나열했습니다.

내 주요 의도는 메시지의 내용을 추출하는 것입니다. 예를 들어, "여기에 메시지 하나"와 같은 메시지가 나타납니다.

다음 코드는 지금 사용하고 있습니다.

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) 

전화는 GSM 모뎀에서 읽는 데 사용하는 직렬 객체입니다. (6)이다

다음

m.group이 첫 번째 메시지의 메시지 내용을 캡처 "여기에 메시지 하나"

가 어떻게이 모든 메시지뿐만 아니라 첫 번째의 내용과 일치 할 수 있습니다.

멀티 라인 플래그 설정을 시도했지만 작동하지 않았습니다. re.search() 대신 re.findall()도 사용하지 않았습니다.

또한 re.search에 의해 반환 된 match 개체는 반복 할 수 없습니다.

도와주세요. 메시지가 줄 바꿈에 항상있는 경우

+0

질문에 메시지를받는 Python 프로그램을 추가 할 것을 요청할 수 있습니까? – Abraham

답변

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()을 사용하는 질문에서 비롯된 것입니다. 그리고 나서 정규 표현식 패턴을 사용합니다. \n을 사용하는 샘플이기 때문에 \r\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 
+0

아, finditer! 그것을 시도해 주셔서 감사합니다! – Anon

0

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

그룹 1은 내가 당신의 자료를 얻을 수 없기 때문에 그냥 샘플을 사용자의 요구 메시지

+0

감사합니다. 최대한 빨리 시도해보십시오.) – Anon

3

regexp를 사용하면 다른 휴대 전화 동작의 변형을 처리 할 수 ​​없으므로 매우 강력한 솔루션이 아닙니다.당신의 예에서 응답의 형식은

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

하지만 다른 전화는

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

공지 사항처럼 등 매개 변수, 아무것도 대 ""의 차이를 응답을 제공 할 것입니다. 27.005 체크 아웃, 텍스트 모드에서의 응답을 구문은

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

<alpha> 실제로 선택이다. 예, 아마도 이것을 고려하는 정규 표현식을 작성할 수는 있지만 two problems land으로 방황 할 수 있습니다. 나는 당신이하는 것이 좋습니다 무엇


응답의 적절한 분석을하고로 전환하는 것, 즉 : 예상 매개 변수 형식 (및 현재 상태)에 따라 덩어리의 첫 번째 문자와 사전에 시작합니다. 전화 번호를 exctract하는 빠르고 더러운 방법은 this answer을 참조하십시오. 아래에 설명 된 알고리즘만큼 강력하지는 않습니다 (예 : comma + 2이 너무 많은 것으로 가정). 파싱 ​​응답

절대 정확한 알고리즘은 다음

매치 라인 (예컨대 +CMGL:)의 시작에 접두사. 그런 다음 토큰 차별화 구문 분석을 시작합니다

  • 공백 ' ' 또는 '\t'
  • 쉼표를 ','
  • 따옴표 '"'
  • 캐리지 리턴 '\r'
  • 줄 바꿈 '\n'
  • 어떤 - 비 공백 - 쉼표 - 비 - 이중 인용 부호 - 비 - 비 - 비 - 비 - 문자 -

각 매개 변수에 대해 선행 공백을 무시하여 시작하십시오. 쉼표를 가져 오는 경우 매개 변수가 없으면 다음 매개 변수를 구문 분석하는 데 사용됩니다. 캐리지 리턴을 얻으려면 다음 문자가 줄 바꿈이어야하고 줄 끝에 도달해야합니다. non-white-space-non ... 문자를 얻는다면 이것은 수치 매개 변수의 시작입니다. 이 매개 변수에 이어 공백이 아닌 모든 문자를 모으십시오. 다음에 나오는 유일한 합법적 인 문자는 공백 또는 캐리지 리턴이 오는 0 이상의 공백이어야합니다. 큰 따옴표 문자를 다음 큰 따옴표 문자로 가져 오는 것이 문자열의 끝 부분입니다 (이 문자열은 큰 따옴표 문자가 포함되어 있어도 이스케이프되지만 \"이 아니기 때문에 안전하고 정확합니다). 다음에 나오는 유일한 합법적 인 문자는 공백 또는 캐리지 리턴이 뒤에 오는 0 개 이상의 공백이어야합니다.

위의 내용은 처음에는 다소 압도적 인 것처럼 보일 수 있지만, 다루기 시작하면 실제로 그렇게 복잡하지는 않습니다.

+0

정말 통찰력있는 와우! 빨리 시험해 보시고 어떻게 움직이는 지 보시고, 감사합니다 :) – Anon