регулярное выражение - инкрементная замена - PullRequest
1 голос
/ 06 июля 2010

Есть ли способ сделать целочисленную инкрементную замену только с помощью регулярного выражения.

Вот проблема, у меня есть текстовый файл, содержащий 1 000 000 строк, все начинающиеся с%

Я хотел бы заменить # на целое число постепенно, используя регулярное выражение.

input:

% line one

% line two

% line three

...

output:

1 line one

2 line two

3 line three

...

Ответы [ 8 ]

5 голосов
/ 06 июля 2010
n = 1
with open('sourcefile.txt') as input:
    with open('destination.txt', 'w') as output:
        for line in input:
            if line.startswith('%'):
                line = str(n) + line[1:]
                n += 1
            output.write(line)
4 голосов
/ 06 июля 2010

Хотя эту проблему лучше всего решить, прочитав файл построчно и проверив первый символ с помощью простых строковых функций, вот как вы будете выполнять пошаговую замену строки в Java:

Pattern p = Pattern.compile("^%");
Matcher m = p.matcher(text);
StringBuffer sb = new StringBuffer();
int i = 0;
while (m.find()) {
    m.appendReplacement(sb, String.valueOf(i++));
}
m.appendTail(sb);

return sb.toString();
4 голосов
/ 06 июля 2010

Вот способ сделать это на Python

import re
from itertools import count
s="""
% line one
% line two
% line three"""

def f():
    n=count(1)
    def inner(m):
        return str(next(n))
    return inner

new_s = re.sub("%",f(),s)

или вы можете использовать там лямбда-функцию, например, так:

new_s = re.sub("%",lambda m,n=count(1):str(next(n)),s)

Но вообще проще и лучше пропустить регулярное выражение

from __future__ import print_function   # For Python<3
import fileinput

f=fileinput.FileInput("file.txt", inplace=1)
for i,line in enumerate(f):
    print ("{0}{1}".format(i, line[1:]), end="")

Поскольку все строки начинаются с "%", нет необходимости даже смотреть на этот первый символ

0 голосов
/ 05 августа 2010
import re, itertools
counter= itertools.count(1)
replacer= lambda match: "%d" % counter.next()
text= re.sub("(?m)^%", replacer, text)

counter - это ... счетчик :).replacer - это функция, возвращающая значения счетчика в виде строк.Регулярное выражение "(?m)^%" истинно для каждого % в начале строки (обратите внимание на многострочный флаг).

0 голосов
/ 06 июля 2010

Вот версия C # (3.0+):

string s = "% line one\n% line two\n% line three";
int n = 1;
s = Regex.Replace(s, @"(?m)^%", m => { return n++.ToString(); });
Console.WriteLine(s);

выход:

1 line one
2 line two
3 line three

Конечно, это требует, чтобы весь текст был загружен в память. Если бы я делал это по-настоящему, я бы, вероятно, использовал поэтапный подход.

0 голосов
/ 06 июля 2010

И версия PHP для хорошей меры:

$input = @fopen('input.txt', 'r');
$output = @fopen("output.txt", "w");

if ($input && $output) {
    $i = 0;
    while (!feof($input)) {
        $line = fgets($input);
        fputs($output, ($line[0] === '%') ?
            substr_replace($line, ++$i, 0, 1) :
            $line
        );
    }
    fclose($input);
    fclose($output);
}

И только потому, что вы можете, Perl с однострочным выражением (да, с регулярным выражением)

perl -i.bak -pe 'BEGIN{$i=1} (s/^%/$i/) && $i++' input.txt
0 голосов
/ 06 июля 2010

в python re.sub принимает функцию в качестве параметра, см. http://docs.python.org/library/re.html#re.sub

0 голосов
/ 06 июля 2010

В зависимости от вашего выбора языка (вы перечислили несколько) PHP preg_replace_callback () может быть подходящей функцией для использования

$text = "% First Line\n% Second Line\n% Third Line";

function cb_numbers($matches)
{
    static $c = 1;

    return $c++;
}
$text = preg_replace_callback(
            "/(%)/",
            "cb_numbers",
            $text);

echo $text;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...