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

时间:2015-02-27 21:58:56

标签: python regex regex-negation

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

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

结果:

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

我所拥有的正确匹配:

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

然而,我显然不能用$ 1 $ 2取代它。我不能使用“\ d +,\ d +”,因为它会匹配12,1425073747,这不是我想要的。如果有人可以解释如何以递归方式解析出值得赞赏的值。

3 个答案:

答案 0 :(得分:2)

这应该适合你:

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

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

答案 1 :(得分:0)

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++ 函数。当然,您可以使用任何您想要的编码。

答案 2 :(得分:-1)

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

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)