如何多次替换字符串?

时间:2013-04-18 17:34:49

标签: python regex

我有10 000行源代码,有大量重复。所以我在文件中读到文字。

示例:

    assert PyArray_TYPE(real0) == np.NPY_DOUBLE, "real0 is not double"
    assert real0.ndim == 1, "real0 has wrong dimensions"
    if not (PyArray_FLAGS(real0) & np.NPY_C_CONTIGUOUS):
        real0 = PyArray_GETCONTIGUOUS(real0)
    real0_data = <double*>real0.data

我想用

替换这种模式的所有出现
    real0_data = _get_data(real0, "real0")

其中real0可以是任何变量名[a-z0-9] +


所以不要对源代码感到困惑。代码没关系,这是文本处理和正则表达式。

这是我到目前为止所做的:

    PATH = "func.pyx"
    source_string = open(PATH,"r").read()

    pattern = r"""
    assert PyArray_TYPE\(([a-z0-9]+)\) == np.NPY_DOUBLE, "([a-z0-9]+) is not double"
    assert ([a-z0-9]+).ndim == 1, "([a-z0-9]+) has wrong dimensions"
    if not (PyArray_FLAGS(([a-z0-9]+)) & np.NPY_C_CONTIGUOUS):
       ([a-z0-9]+) = PyArray_GETCONTIGUOUS(([a-z0-9]+))
    ([a-z0-9]+)_data = ([a-z0-9]+).data"""

1 个答案:

答案 0 :(得分:1)

您可以在任何支持多行正则表达式搜索和替换的文本编辑器中执行此操作。

我使用Komodo IDE来测试它,因为它包含一个优秀的正则表达式测试器(“Rx Toolkit”),用于试验正则表达式。我认为还有一些这样的在线工具。相同的正则表达式适用于免费的Komodo Edit。它也适用于支持与Perl兼容的正则表达式的大多数其他编辑器。

在Komodo中,我使用了选中了Regex选项的Replace对话框来查找:

assert PyArray_TYPE\((\w+)\) == np\.NPY_DOUBLE, "\1 is not double"\s*\n\s*assert \1\.ndim == 1, "\1 has wrong dimensions"\s*\n\s*if not \(PyArray_FLAGS\(\1\) & np\.NPY_C_CONTIGUOUS\):\s*\n\s*\1 = PyArray_GETCONTIGUOUS\(\1\)\s*\n\s*\1_data = <double\*>\1\.data

并将其替换为:

\1_data = _get_data(\1, "\1")

鉴于此测试代码:

    assert PyArray_TYPE(real0) == np.NPY_DOUBLE, "real0 is not double"
    assert real0.ndim == 1, "real0 has wrong dimensions"
    if not (PyArray_FLAGS(real0) & np.NPY_C_CONTIGUOUS):
        real0 = PyArray_GETCONTIGUOUS(real0)
    real0_data = <double*>real0.data

    assert PyArray_TYPE(real1) == np.NPY_DOUBLE, "real1 is not double"
    assert real1.ndim == 1, "real1 has wrong dimensions"
    if not (PyArray_FLAGS(real1) & np.NPY_C_CONTIGUOUS):
        real1 = PyArray_GETCONTIGUOUS(real1)
    real1_data = <double*>real1.data

    assert PyArray_TYPE(real2) == np.NPY_DOUBLE, "real2 is not double"
    assert real2.ndim == 1, "real2 has wrong dimensions"
    if not (PyArray_FLAGS(real2) & np.NPY_C_CONTIGUOUS):
        real2 = PyArray_GETCONTIGUOUS(real2)
    real2_data = <double*>real2.data

结果是:

    real0_data = _get_data(real0, "real0")

    real1_data = _get_data(real1, "real1")

    real2_data = _get_data(real2, "real2")

那么我是如何从原始代码中获取正则表达式的呢?

  1. 使用().*\的所有实例添加前缀(以便轻松手动搜索和替换)。< / LI>
  2. real0第一个实例替换为(\w+)。这匹配并捕获一串字母数字字符。
  3. real0的其余实例替换为\1。这与(\w+)
  4. 捕获的文本相匹配
  5. 使用\s*\n\s*替换下一行的每个换行符和前导空格。这匹配线上的任何尾随空格,加上换行符,以及下一行的所有前导空格。这样,正则表达式无论其匹配的代码的嵌套级别如何都能正常工作。
  6. 最后,“替换”文字使用\1,它需要原始捕获的文本。

    如果你想这样做,你当然可以在Python中使用类似的正则表达式。我建议使用\w代替[a-z0-9],以使其更简单。另外,不要包括换行符和前导空格;而是使用我使用的\s*\n\s*方法而不是多行字符串。这样,它将独立于我上面提到的嵌套级别。