繁体   English   中英

正则表达式-增量替换

[英]regular expression - incremental replacement

有什么办法只能使用正则表达式进行整数增量替换。

这是问题所在,我的文本文件包含1 000 000行,均以%开头

我想使用正则表达式将#替换为整数。

input:

% line one

% line two

% line three

...

output:

1 line one

2 line two

3 line three

...
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)

这是在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)

或者,您可以在其中使用lambda函数,如下所示:

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="")

由于所有行均以“%”开头,因此无需查看第一个字符

尽管最好通过逐行读取文件并使用简单的字符串函数检查第一个字符来解决此问题,但这是在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();

根据您选择的语言(您已经列出了几种),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;

在python re.sub中接受参数作为参数,请参见http://docs.python.org/library/re.html#re.sub

还有一个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

这是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

当然,这需要将整个文本加载到内存中。 如果我是真正做到这一点,我可能会采用逐行方法。

import re, itertools
counter= itertools.count(1)
replacer= lambda match: "%d" % counter.next()
text= re.sub("(?m)^%", replacer, text)

counter是…柜台:)。 replacer是一个将计数器值作为字符串返回的函数。 对于行首的每个%"(?m)^%"正则表达式都是正确的(请注意多行标志)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM