python re.split():如何保存一些分隔符(而不是使用括号保存所有分隔符)

python re.split():如何保存一些分隔符(而不是使用括号保存所有分隔符),python,split,Python,Split,以下句子: "I am very hungry, so mum brings me a cake! 我希望它被分隔符分割,我希望除了空间之外的所有分隔符也被保存。因此,预期产出为: "I" "am" "very" "hungry" "," "so", "mum" "brings" "me" "a" "cake" "!" "\n" 我目前正在做的是re.split(r'([!:'',(\s+)\n]),text),它可以拆分整个句子,但也节省了很多我

以下句子:

"I am very hungry,    so mum brings me a cake!
我希望它被分隔符分割,我希望除了空间之外的所有分隔符也被保存。因此,预期产出为:

"I"  "am"  "very"  "hungry"   ","   "so", "mum"  "brings"  "me"   "a"   "cake"    "!"    "\n"

我目前正在做的是
re.split(r'([!:'',(\s+)\n]),text)
,它可以拆分整个句子,但也节省了很多我不想要的空格字符。我还尝试了正则表达式
\s |([!:'',(\s+)\n])
,不知何故,这给了我很多空白。

这是因为正则表达式包含一个捕获组。由于该捕获组,它还将在结果中包含匹配项。但这可能是你想要的

唯一的挑战是
过滤出
None
s(以及其他真实值
False
)如果不匹配,我们可以使用以下方法:

def tokenize(text):
    return filter(None, re.split(r'[ ]+|([!:''".,\s\n])', text))

一种方法是用空格包围特殊字符
(,!。\n)
,然后按空格分割:

import re


def tokenize(t, pattern="([,!.\n])"):
    return [e for e in re.sub(pattern, r" \1 ", t).split(' ') if e]


s = "I am very hungry,    so mum brings me a cake!\n"

print(tokenize(s))
输出

['I', 'am', 'very', 'hungry', ',', 'so', 'mum', 'brings', 'me', 'a', 'cake', '!', '\n']

search
findall
在这里可能比
split
更合适:

import re

s = "I am very hungry,    so mum brings me a !#$#@  cake!"

print(re.findall(r'[^\w\s]+|\w+', s))

# ['I', 'am', 'very', 'hungry', ',', 'so', 'mum', 'brings', 'me', 'a', '!#$#@', 'cake', '!']

模式
[^\w\s]+|\w+
的意思是:既不是字母数字也不是空格的符号序列,或者是字母数字序列(即一个单词)

几乎是的副本。为什么将[]+\124;添加到reg表达式中会导致生成大量的非?I@SoManyProblems:因为如果捕获组(括号中的部分)不匹配任何内容,它仍然会为“空”捕获组引入一个
None
。如果您生成多个括号,这甚至会导致大量额外的元素。非常感谢您的回复。为了确认我对您的理解是正确的,您的意思是[]+匹配空格,所以它进行了拆分工作,并且因为它没有(),所以它不会返回任何内容?@SoManyProblems:regex本身有一个
(…)
,一个捕获组。但由于该捕获组未“激活”(它不匹配任何内容),因此它捕获
None
。您能否解释一下该模式是如何以这种方式构建的?为什么[^\w\s]+给出了所有单词,但没有给出带空格字符的单词(如建议的那样)?还有,你为什么在那里放置| w+模式?@SoManyProblems:添加了一个解释
import re

s = "I am very hungry,    so mum brings me a !#$#@  cake!"

print(re.findall(r'[^\w\s]+|\w+', s))

# ['I', 'am', 'very', 'hungry', ',', 'so', 'mum', 'brings', 'me', 'a', '!#$#@', 'cake', '!']