Умножьте с поиском и заменой - PullRequest
3 голосов
/ 23 апреля 2010

Можно ли использовать регулярные выражения для выполнения арифметики? Например, найти все числа в файле и умножить их на скалярное значение.

Ответы [ 6 ]

8 голосов
/ 23 апреля 2010

Этого можно добиться, используя re.sub() с обратным вызовом:

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 (pattern, repl, string [, count])

Если repl является функцией, она вызывается для каждого неперекрывающегося вхождения шаблона.Функция принимает один аргумент объекта сопоставления и возвращает строку замены.

4 голосов
/ 23 апреля 2010

В Perl вы можете сделать это с помощью модификатора / e. Это вызывает замену части выражения. Предполагая, что $ line содержит строку файла

 my $scalar= 4;
 $line =~ s/([\d]+)/$1*$scalar/ge;

Применение этого к каждой строке сделает работу за вас. Например, применяя это к Строка $, содержащая "foo2 bar25 baz", преобразует ее в "foo8 bar100 baz"

2 голосов
/ 23 апреля 2010

Я подготовил небольшой скрипт, который использует re.finditer, чтобы найти все целые числа (вы можете изменить регулярное выражение, чтобы оно могло иметь дело с числами с плавающей запятой или научной нотацией), а затем использовать 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

Если у вас есть file, чьи числа вы хотите масштабировать с коэффициентом fact, вы вызовете скрипт из командной строки как python script.py file fact, и он выведет на STDOUT все масштабированные числа. Конечно, вы можете сделать что-то более полезное, если хотите ...

1 голос
/ 24 апреля 2010

Тем из вас, кто сомневается, что sed может делать арифметику, я предлагаю этот контрпример . Этот еще более дикий.

1 голос
/ 23 апреля 2010

Сами регулярные выражения не могут - они все о тексте - так что sed не может напрямую. Впрочем, достаточно просто сделать что-то подобное на полноценном языке сценариев, таком как python или perl.

0 голосов
/ 24 апреля 2010

Ответ Аймана Хури может быть уменьшен, чтобы быть немного более простым, и imo более читабельным:

>>> import re
>>> repl = lambda m: str(int(m.group(0)) * 2)
>>> print re.sub(r'\d+', repl, '1 a20 300c')
2 a40 600c
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...