Python 与查找和替换相乘

Python 与查找和替换相乘,python,regex,sed,Python,Regex,Sed,正则表达式可以用来执行算术吗?例如,查找文件中的所有数字并将它们乘以一个标量值。正则表达式本身不能,因为它们都是关于文本的,所以sed不能直接使用。但是,用完整的脚本语言(如python或perl)执行类似操作非常简单。您可以通过回调实现这一点: import re def repl(matchobj): i = int(matchobj.group(0)) return str(i * 2) print re.sub(r'\d+', repl, '1 a20 300c') 输出:

正则表达式可以用来执行算术吗?例如,查找文件中的所有数字并将它们乘以一个标量值。

正则表达式本身不能,因为它们都是关于文本的,所以sed不能直接使用。但是,用完整的脚本语言(如python或perl)执行类似操作非常简单。

您可以通过回调实现这一点:

import re

def repl(matchobj):
  i = int(matchobj.group(0))
  return str(i * 2)

print re.sub(r'\d+', repl, '1 a20 300c')
输出:

2 a40 600c
从文档中:

re.sub(模式、应答、字符串[,, 计数])

如果repl是一个函数,则调用它 对于每个不重叠的事件 有规律的。该函数需要一段时间 单个匹配对象参数,以及 返回替换字符串


我准备了一个小脚本,它使用
re.finditer
查找所有整数(您可以更改regexp以便它可以处理浮点或科学记数法),然后使用
map
返回一个缩放数字列表

import re

def scale(fact):
    """This function returns a lambda which will scale a number by a                           
    factor 'fact'"""
    return lambda val: fact * val

def find_and_scale(file, fact):
    """This function will find all the numbers (integers) in a file and                        
    return a list of all such numbers scaled by a factor 'fact'"""
    num = re.compile('(\d+)')
    scaling = scale(fact)
    f = open(file, 'r').read()
    numbers = [int(m.group(1)) for m in num.finditer(f)]
    return map(scaling, numbers)

if __name__ == "__main__":
    import sys
    if len(sys.argv) != 3:
        print "usage: %s file factor" % sys.argv[0]
        sys.exit(-1)
    numbers = find_and_scale(sys.argv[1], int(sys.argv[2]))
    for number in numbers:
        print "%d " % number

如果您有一个
文件
,您希望通过因子
事实
来缩放该文件的数字,那么您可以从命令行将脚本调用为
python script.py file fact
,它将打印到
STDOUT
所有缩放的数字。当然,如果您愿意,您可以做一些更有用的事情…

在perl中,您可以使用/e修饰符来完成这项工作。这将导致计算表达式的替换部分。假设$line包含文件的一行

 my $scalar= 4;
 $line =~ s/([\d]+)/$1*$scalar/ge;
将此应用于每一行将为您完成这项工作。例如,将此应用于
包含“foo2 bar25 baz”的$line将其转换为“foo8 bar100 baz”

Ayman Hourieh的答案可以简化为更简单一点,并且更易于阅读:

>>> import re
>>> repl = lambda m: str(int(m.group(0)) * 2)
>>> print re.sub(r'\d+', repl, '1 a20 300c')
2 a40 600c

对于那些怀疑塞德能做算术的人,我提供这个。甚至更疯狂。

我相信你可以通过黑客破解,但我发现任何“扩展”使用regexp的行为都是无法维护的——即使它们被用于预期用途,也会让人大吃一惊!只是一个想法…@Arrieta-没错,regexp是一条路要走。这是一个快速而肮脏的一次性脚本,因此不会引起维护人员的愤怒。我不知道
re.sub
的“迭代器质量”。谢谢你的发帖。谢谢,你的解决方案非常优雅。这是很好的反馈
lambda
提供了一种创建匿名函数的方法。如果你最终给它起了一个名字,那么使用
def
通常会更清晰。这是一个意见问题,因为对于这样一个简单的函数使用几行代码并不是天生的“清晰”。这些都是巧妙的技巧,但是它们表明,对于算术结果,您必须非常有创造性地使用sed-to。感谢您提醒我perl中总是有一行解决方案。sed可以做到这一点。由于sed脚本中存在条件跳跃,因此sed在理论上是图灵完备的。实际上,脚本的长度和行数是有限制的。在互联网上的某个地方,有一个用于完整计算器的sed脚本,包括trig和exp函数。但这种任务并不是我考虑使用SED的任务。