我有一个大小约为5MB的二进制文件..它有很多散布的文本..和控制字符..
这实际上相当于SITATEX Application(来自SITA)的outlook .pst文件。
该文件包含所有发送和接收来自外部世界的文本消息...(但文本必须通过二进制控制字符提取)..所有文本消息都清晰可用...带行结束^ M个字符......等等。
例如:假设^ @ ^ X是控制字符... \ xaa和HEX aa等等,它们围绕我所需的文本提取加载。
^@^@^@^@^@^@^@^@^@^@^@BLLBBCC^X^X^X^X^X^X^X^X^X
^X^X^X
MVT^M
EA1123 TEXT TEXT TEXT^M
END^M
\xaa^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
^@^@^@^@^@^@^@^@^@^@^@TTBBTT^X^X^X^X^X^X^X^X^X
^X^X^X blah blah blah... of control characters.. and then the message comes..
MVT MESSAGE 2
ED1123
etc.
等等......有几条消息。
使用Perl ..很容易做到:
while (<>) {
use regular expression to split messages
m/ /
}
如何在python中轻松实现这一点..
在文本文件示例中......我有兴趣看到.. BLLBBCC ...以及MVT和EA1123等等。
请帮助...如果在python中非常困难......我将不得不考虑perl本身的逻辑...因为它(perl)并没有给我带来很多错误至少对于二进制和文本的循环部分..和正则表达式。
感谢。
在阅读完答案/评论后更新02Jan
在浏览了S.Lott的评论和其他人之后......这就是我所在的地方......它的工作效率已经达到了80%。
import fileinput
import sys
import re
strfile = r'C:\Users\' \
r'\Learn\python\mvt\sitatex_test.msgs'
f = open(strfile, 'rb')
contents = f.read() # read whole file in contents
#extract the string between two \xaaU.. multiline pattern match
#with look ahead assertion
#and this is stored in a list with all msgs
msgs = re.findall(r'\xaaU.*?(?=\xaaU)', contents, re.I|re.DOTALL|re.M)
for msg in msgs:
#loop through msgs.. to find the first msg then next and so on.
print "## NEW MESSAGE STARTS HERE ##"
#for each msg split the lines.. to read line by line
# stored as list in msglines
msglines = msg.splitlines()
line = 0
#then process each msgline with a message
for msgline in msglines:
line += 1
#msgline = re.sub(r'[\x00]+', r' ', msgline)
mystr = msgline
print mystr
textstrings = re.findall(r'[\x00\x20-\x7E]+', msgline)
到目前为止一直这么好..我仍然没有完全完成..因为我需要逐行逐字解析文本..以拾取(作为示例)原始地址和标题,主题行,消息body ...通过控制字符解析消息。
现在我不知道......如何逐行打印转换为\x00\x02..
等控制字符(使用\xHH
格式)...但是保留正常的可读文本。< / p>
例如..说我有这个:假设^@
和^X
是一些控制字符
line1 = '^@UG^@^@^@^@^@^@^@^@^@^@BLLBBCC^X^X^X^X^X^X^X^X^X'
(在第一行)。
当我在IDLE上打印该行时,print line1
..它只打印前两个或三个字符..并且由于控制字符被阻塞而忽略其余字符。
但是,当我用这个打印时:print re.findall(r'.*', line1)
['\xaaUG\x02\x05\x00\x04\x00\x00\x00\x05\x00\x00\x00....
x00\x00\x00..BLLBBCC\x00\x00N\x00N\\x00
002 010 180000 DEC 11', '']
它打印得很好,所有控制字符转换为\ xHH格式..和ascii文本完好无损..(正如我想要的那样)..有一个捕获..列表有两个项目..用&#39; &#39;最后。
使用re.findall(r'.*', line1)
是唯一简单的解决方案..进行此转换..还是有任何其他简单的方法..将'\x00string'
转换为\ xHH和TEXT(它是一个可打印的字符或空格。)
另外..任何其他有用的评论都可以很好地解决问题。
感谢。
更新2Jan2011 - 第2部分
我发现re.findall(r'.+', line1)
剥离了
['\xaaUG\x02\x05\x00\x04\x00\x00\x00\x05\x00\x00\x00....
x00\x00\x00..BLLBBCC\x00\x00N\x00N\\x00
002 010 180000 DEC 11']
没有额外的空白&#39;&#39;列表中的项目。经过多次试验和错误后,这一发现。
我仍然需要帮助才能完全消除列表,但只返回一个字符串。 像这样:
'\xaaUG\x02\x05\x00\x04..BLLBBCC..002 010 180000 DEC 11'
在05Jan上添加了信息:
@John Machin
1)\ xaaU是消息之间的分隔符..在示例中..我可能刚刚在示例中省略了。请参阅下面的一条以\ xaaU结尾的实际消息(但遗漏了)。
以下文本来自repr(r'\xaaU.*?(?=\xaaU)'
之间的消息)
我正在尝试理解二进制格式..这是一个发送的典型消息 第一个&#39; JJJOWXH&#39;是发件人地址..后面有7个字母数字的接收器地址。基于发件人地址..我可以知道这是一个&#39; SND&#39;或者&#39; RCV&#39; ..作为来源是&#39; JJJOWXH&#39; ...这个消息是&#39; SND&#39;因为我们是JJJOWXH&#39;。
该消息发送至:JJJKLXH .... JJJKRXH ....等等。
所有.. \ x00000000完成后..
sita标题和主题开始
在这种特殊情况下...... "\x00QN\x00HX\x00180001 \x00"
这是标题..我只对\ x00之间的所有内容感兴趣。
并且身体接下来..在最后的\ x00或任何其他控制角色之后......在这种情况下......它是:
COR \ r \ n \ nMVT \ r \ nHX9136 / 17.BLNZ.JJJ \ r \ nAD2309 / 2314 EA0128 BBB \ r \ nDLRA / CI / 0032/0022 \ r \ nSI EET 02:14 HRS \ r \ n RA / 0032由于 晚期ARVL ACFT \ r \ n CI / 0022 OFFLOAD OVERHANG PALLET DUE INADQUATE 包装导致\ r \ n空间问题
一旦可读文本结束...出现的第一个控制字符,直到结束\ xaaU被忽略...在上述情况下......&#34;空格问题&#34; ..是最后一个。然后控制字符开始......所以要忽略......有时控制字符不存在,直到下一个\ xaaU。
这是一条完整的信息。
&#34; \ xaaU \ X1C \ X04 \ X02 \ X00 \ X05 \ X06 \ X1F \ X00 \ X19 \ X00 \ X00 \ X00 \ XC4 \ x9d \ xedN \ X1A \ X00 \ X02 \ X02 \ x00B \ X02 \ X02 \ x00E \ X02 \ X07 \ X00 \ XFF \ XFF \ X00 \ X00 \ XFF \ XFF \ X00 \ X00 \ XFF \ XFF \ X00 \ x00M \ X02 \ XEC \ X00 \ XFF \ XFF \ X00 \ X00 \ X00 \ X00?\ x02M \ X02 \ XEC \ X00 \ XFF \ XFF \ X00 \ X00 \ XFF \ XFF \ X00 \ X00 \ XFF \ XFF \ X00 \ X00 \ XFF \ XFF \ X00 \ X00 \ XFF \ XFF \ X00 \ X00:\ X03 \ X10 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ X00 \ 0x7F部分\ x00JJJOWXH \ X00 \ x05w \ x01x \ X01 \ X00 \ x01JJJKLXH \ X00 \ X00 \ 0x7F部分\ X01 \ X80 \ X01 \ X00 \ x01JJJKRXH \ x00F \的x87 \ X01 \ X88 \ X01 \ X00 \ x01JJJFFXH \ X00 \ XFF \ X8F \ X01 \ X90 \ X01 \ X00 \ x01JJJFCXH \ X00 \ XFF \ X97 \ X01 \ X98 \ X01 \ X00 \ x01JJJFAXH \ X00 \ X00 \ x9f \ X01 \ XA0 \ X01 \ X00 \ x01JJJKPXH \ X00 \ X00 \ XA7 \ X01 \ xa8 \ X01 \ X00 \ x01HAKUOHU \ X00 \ X00 \ XAF \ X01 \ XB0 \ X01 \ X00 \ x01BBBHRXH \ X00 \ X00 \ XB7 \ X01 \ XB8 \ X01 \ X00 \ x01BBBFFHX \ X00 \ X00 \ XBF \ X01 \ XC0 \ X01 \ X00 \ x01BBBOMHX \ X00 \ X00 \ xc7 \ X01 \ xc8 \ X01 \ X00 \ x01BBBFMXH \ X00 \ X00 \ XCF \ X01 \ XD0 \ X01 \ X00 \ x01JJJHBER \ X00 \ X00 \ XD7 \ X01 \ XD8 \ X01 \ X00 \ x01BBBFRUO \ X00 \ X00 \ XDF \ X01 \ xe0 \ X01 \ X00 \ x01BBBKKHX \ X00 \ X00 \ XE7 \ X01 \ xe8 \ X01 \ X00 \ x01JJJLOTG \ X00 \ X01 \ XEF \ X01 \ XF0 \ X01 \ X00 \ x01JJJLCTG \ X00 \ X00 \ XF7 \ X01 \ XF8 \ X01 \ X00 \ x01HDQOMTG \ X005 \ XFF \ X01 \ X00 \ X02 \ X00 \ x01CHACSHX \ x00K \ X07 \ X02 \ X08 \ X02 \ X00 \ x01JJJKZXH \ x00F \ X0F \ X02 \ X10 \ X02 \ X00 \ x01BBBOMUO \ X00 \ x17 \ x02 \ x18 \ x02 \ x00 \ x01BBBORXH \ x00 \ x1f \ x02 \ X02 \ X00 \ x01BBBOPXH \ x00W&#39; \ X02(\ X02 \ X00 \ x01CHACSHX \ X00 / \ X020 \ X02 \ X00 \ x01JJJDBXH \ x0007 \把X028 \ X02 \ x00010000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ X00 \ x00000000 \ x00QN \ x00HX \ x00180001 \ x00COR \ r \ nMVT \ r \ nHX9136 / 17.BLNZ.JJJ \ r \ nAD2309 / 2314 EA0128 BBB \ r \ nDLRA / CI / 0032/0022 \ r \ nSI EET 02:14 HRS \ r \ n RA / 0032由于 晚期ARVL ACFT \ r \ n CI / 0022 OFFLOAD OVERHANG PALLET DUE INADQUATE 包装领先于\ r \ n空间 问题\ x00D- \ xedN \ X00 \ X04 \ X1A \ x00t&LT; \ X93 \ x01x \ x00M_ \ X00&#34;
2)我没有使用。+再次使用&#39; repr&#39;众所周知。
3)每条消息都是多行的..我需要保留所有的控制字符,以便对这种专有格式有所了解。这就是为什么我需要repr才能看到它。
希望这可以解释......这只是文件中1000条中的1条消息...而且有些是&#39; SND&#39;还有一些是RCV&#39; ......以及RCV&#39;不会有&00; 000000&#39; ..偶尔会有规则的小例外......但通常都可以。
任何进一步的建议任何人..我仍在使用该文件..以完整的方式检索文本...包含发件人和收件人地址。
谢谢。
答案 0 :(得分:2)
问:如何阅读文件?二进制和文本穿插
答:不要打扰,只需将其作为普通文本阅读,您就可以保持二进制/文本二分法(否则您将无法轻易地对其进行正则表达式)
fh = open('/path/to/my/file.ext', 'r')
fh.read()
如果您因某种原因想要稍后阅读二进制文件,只需在打开的第二个输入中添加一个b:
fh = open('/path/to/my/file.ext', 'rb')
问:消除不必要的控制字符
答:使用python re模块。你的下一个问题有点问
问:在两个\ xaa有用的文本信息之间解析消息\ xaa(HEX'aa')
答:re模块有一个findall函数,可以像你(大部分)一样工作。
import re
mytext = '\xaaUseful text that I want to keep\xaa^X^X^X\xaaOther text i like\xaa'
usefultext = re.findall('\xaa([a-zA-Z^!-~0-9 ]+)\xaa', mytext)
问:打印出所需内容
* A:有打印功能......
print usefultext
问:循环遍历所有行......以及更多文件。
fh = open('/some/file.ext','r')
for lines in fh.readlines():
#do stuff
我会让你找出os模块,找出存在哪些文件/如何迭代它们。
答案 1 :(得分:2)
Python也支持正则表达式。我不会说Perl,所以我不确切知道你的Perl代码是做什么的,但是这个Python程序可能对你有所帮助:
import re
with open('yourfile.pst') as f:
contents = f.read()
textstrings = re.findall(r'[\x20-\x7E]+', contents)
这将为您提供文件中一个或多个ASCII可打印字符的所有字符串的列表。这可能不是你想要的,但你可以从那里调整它。
请注意,如果您使用的是Python 3,那么您必须担心二进制和文本数据之间的区别,它会变得有点复杂。我假设您使用的是Python 2。
答案 2 :(得分:1)
你说:
我仍然需要帮助才能完全消除列表,但只返回一个字符串。像这样
换句话说,你有foo = [some_string]
并且你正在做print foo
,repr(some_string)
作为一方做print repr(foo[0])
,但将其用方括号括起来,你不想要。所以只需\xaaU
。
似乎有几件事无法解释:
您说有用的文字被\xaa
括起来,但在示例文件中,而不是该分隔符的两次出现,在开头附近只有U
(缺少\n
) ,别无其他。
你说
我发现re.findall(r'。+',line1)剥离到...
这实际上是剥离\r
(但不是>>> re.findall(r'.+', 'abc\r\ndef\r\n\r\n')
['abc\r', 'def\r', '\r']
!!) - 我认为在尝试恢复电子邮件时,换行符值得保留。
\r
你对\xab
个字符做了什么?你测试了多行消息吗?您是否测试了多消息文件?
可以猜测是谁或什么意图消耗你的输出;你写的
我需要逐行逐字解析文本
但你似乎过分担心用“清晰”打印信息。 <{1}}而不是胡言乱语。
看起来您最新代码(for msgline in msglines:
等)中的最后6行应该缩进一级。
是否有可能澄清以上所有内容?