Python 追加';0x';在字符串中的十六进制数之前

Python 追加';0x';在字符串中的十六进制数之前,python,parsing,Python,Parsing,我正在解析一个xml文件,其中包含基本表达式(如id*10+2)。我试图做的是计算表达式,以实际获得值。为此,我使用了运行良好的eval()方法 唯一的问题是这些数字实际上是十六进制数。如果每个十六进制数的前缀都是“0x”,那么eval()方法可以很好地工作,但是我找不到一种方法来实现它,在这里也找不到类似的问题。如何以干净的方式完成此任务?使用此模块 不过,请注意,如果对eval的输入无效,则它将无法工作。还有使用eval的方法 如果您的十六进制数字有小写字母,则可以使用: >>&

我正在解析一个xml文件,其中包含基本表达式(如
id*10+2
)。我试图做的是计算表达式,以实际获得值。为此,我使用了运行良好的
eval()
方法

唯一的问题是这些数字实际上是十六进制数。如果每个十六进制数的前缀都是“0x”,那么
eval()
方法可以很好地工作,但是我找不到一种方法来实现它,在这里也找不到类似的问题。如何以干净的方式完成此任务?

使用此模块

不过,请注意,如果对
eval
的输入无效,则它将无法工作。还有使用
eval
的方法

如果您的十六进制数字有小写字母,则可以使用:

>>> re.sub(r'(?<!i)([\da-fA-F]+)', r'0x\1', 'id*a+b')
'id*0xa+0xb'

>>re.sub(r'(?如果可以将表达式解析为单个数字,那么我建议使用:


小心使用
eval
!切勿在不受信任的输入中使用它


如果只是简单的算术,我会使用一个自定义解析器(在野外有大量的示例)…并且使用解析器生成器(flex/bison、antlr等)是一项有用且容易忘记的技能,因此这可能是一个很好的机会来刷新或学习它。

一个选项是使用
解析器
模块:

import parser, token, re

def hexify(ast):
    if not isinstance(ast, list):
        return ast
    if ast[0] in (token.NAME, token.NUMBER) and re.match('[0-9a-fA-F]+$', ast[1]):
        return [token.NUMBER, '0x' + ast[1]]
    return map(hexify, ast)

def hexified_eval(expr, *args):
    ast = parser.sequence2st(hexify(parser.expr(expr).tolist()))
    return eval(ast.compile(), *args)

>>> hexified_eval('id*10 + BABE', {'id':0xcafe})
567466
这比正则表达式解决方案更简洁,因为它只尝试替换已被确定为名称或数字(看起来像十六进制数字)的令牌。它还正确处理更通用的python表达式,如
id*10+len('BABE')
(它不会用
'0xBABE'
替换
'BABE'


OTOH,正则表达式解决方案更简单,可能会覆盖所有需要处理的情况。

我自己正要点击enter;)我尝试了这个解决方案,但它只适用于低于“A”的数字。只要有十六进制字符(即从“A”到“f”),它就不会被替换(\d+不允许字母作为数字)@skndo感谢您指出这一点。我已经更新了我的解决方案,事实上它工作得很好…只要
Id
不是要解析的表达式的一部分!它将被
I0xd
替换(我没有看到它的出现!)事实上,我编辑了你的代码,因为变量是
Id
。非常感谢你快速而有用的回答。你是否要解析
CAFE+BABE
?CAFE和BABE都是十六进制数。我唯一需要注意的变量名是
Id
。因此理想情况下,它需要
CAFE+BABE
并将其转换为
0xCAFE+0xBABE
对于
“open('/tmp/a-file-on-your-system','w')。write(\'care!\”)之类的表达式呢
?你试过
eval
ing吗?@Joe谢谢你提醒我,但正如我对fortran的回答所评论的那样,这只是快速原型设计。稍后它将被更安全的东西所取代。当然,有些事情应该经常指出(eval,SQL注入)仅供记录。可能有人会看到以前不知道的问题。例如,我看到很多关于SQL注入漏洞的问题,所以我知道这总是值得一提的。这确实是一个很好的解决方案,但整个问题是正确拆分表达式(这有点困难,因为十六进制数字中的字母)谢谢。谢谢你的建议,我确实读过一些关于你可以用<代码>()(<代码)>的方法。非常吓人:D,但是我用这个来做快速原型(稍后我会为XML文件写一个C++阅读器/解析器)。另外,它主要在一个封闭的网络中运行,没有连接到Internet!但我同意你的观点,将其保留在最终代码中不是一个好主意。是的,原型设计很好:)。。。但请注意,它是如此的方便,以至于你冒着永远离开它的风险!XD(发生在我身上:p)哈哈,我知道这有多危险,编程人员很懒:D但人们会跟着我读代码,他们不会让代码这样走(这是最好的)很好的解决方案,我喜欢!因为我只是原型设计和处理非常基本的表达式,所以我保持简单,但这种解决方案似乎避免了一些问题
>>> int("CAFE", 16)
51966
import parser, token, re

def hexify(ast):
    if not isinstance(ast, list):
        return ast
    if ast[0] in (token.NAME, token.NUMBER) and re.match('[0-9a-fA-F]+$', ast[1]):
        return [token.NUMBER, '0x' + ast[1]]
    return map(hexify, ast)

def hexified_eval(expr, *args):
    ast = parser.sequence2st(hexify(parser.expr(expr).tolist()))
    return eval(ast.compile(), *args)

>>> hexified_eval('id*10 + BABE', {'id':0xcafe})
567466