正则表达式:删除引号分隔字符串 [python] 之间的所有逗号

Regex : Remove all commas between a quote separated string [python]

什么是合适的正则表达式来删除字符串中的所有逗号:

12, 1425073747, "test", "1, 2, 3, ... "

结果:

12, 1425073747, "test", "1 2 3 ... "

我拥有的正确匹配的内容:

"((\d+), )+\d+"

但是,我显然不能用$1 $2来代替这个。我不能使用 "\d+, \d+" 因为它会匹配 12, 1425073747 这不是我想要的。如果有人可以解释如何递归解析值,那也将不胜感激。

这应该适合你:

>>> input = '12, 1425073747, "test", "1, 2, 3, ... "';
>>> print re.sub(r'(?!(([^"]*"){2})*[^"]*$),', "", input);
12, 1425073747, "test", "1 2 3 ... "

(?!(([^"]*"){2})*[^"]*$) 仅在 quotea 内匹配文本——避免匹配逗号后偶数个引号。

您可以使用带有简单 r'"[^"]*"' 正则表达式的 re.sub 并将匹配对象传递给用作替换参数的可调用对象,您可以在其中进一步操作匹配:

import re
text = '12, 1425073747, "test", "1, 2, 3, ... "'
print( re.sub(r'"[^"]*"', lambda x: x.group().replace(",", ""), text) )

参见Python demo

如果引号之间的字符串可能包含转义引号,请使用

re.sub(r'(?s)"[^"\]*(?:\.[^"\]*)*"', lambda x: x.group().replace(",", ""), text)

这里,(?s)re.S / re.DOTALL 标志的内联版本,其余是双引号字符串文字匹配模式。

奖金

  • 删除双引号之间的所有空格:re.sub(r'"[^"]*"', lambda x: ''.join(x.group().split()), text)
  • 删除双引号内的所有非数字字符:re.sub(r'"[^"]*"', lambda x: ''.join(c for c in x.group() if c.isdigit()), text)
  • 删除双引号内的所有数字字符:re.sub(r'"[^"]*"', lambda x: ''.join(c for c in x.group() if not c.isdigit()), text)

anubhava 提供的解决方案非常有用,事实上,这是我找到的唯一适用于指南的解决方案 - 这意味着真正可靠地删除了引用文本中的分号。然而,在一个 640 kB 的文本文件(是的,640)上使用它需要大约 3 分钟,这即使在老式的 i5 上也是不可接受的。

我的解决方案是实现一个 C++ 函数:

#include <string>
#include <cstring>
#include <iostream>

using namespace std;

extern "C" // required when using C++ compiler
    const char *
    erasesemi(char *s)
{
    bool WeAreIn = false;
    long sl = strlen(s);
    char *r = (char*) malloc(sl+1);
    strcpy(r, s);
    for (long i = 0; (i < (sl - 1)); i++)
    {
        if (s[i] == '"')
        {
            WeAreIn = not(WeAreIn);
        }
        if ((s[i] == ';') & WeAreIn)
        {
            r[i] = ',';
        }
        else
        {
            r[i] = s[i];
        }
    }
    return r;
}

根据我在互联网上找到的,我使用了这个setup.py

from setuptools import setup, Extension

# Compile *mysum.cpp* into a shared library
setup(
    # ...
    ext_modules=[Extension('erasesemi', ['erasesemi.cpp'],), ],
)

之后你必须 运行

python3 setup.py build

主要代码中的相应行是:

import ctypes
import glob
libfile = glob.glob(
    'build/lib.linux-x86_64-3.8/erasesemi.cpython-38-x86_64-linux-gnu.so')[0]

mylib = ctypes.CDLL(libfile)

mylib.erasesemi.restype = ctypes.c_char_p
mylib.erasesemi.argtypes = [ctypes.c_char_p]

..

data3 = mylib.erasesemi(str(data2).encode('latin-1'))

像这样,它在 < 1 秒内产生了预期的结果。最棘手的部分是找出如何将带有德语字符的字符串传递给 c++ 函数。当然,您可以使用任何您想要的编码。