Python 使用 re 在字符之间创建空格,方括号中的字符除外
Python using re to create spaces between characters except for those in square brackets
我有一个数据框:
d1 ={'letters':['ABCDE[NOT]FGH', 'CCGF[NOT]HI', 'MPJ[NOT]L', 'MNA[NOT]PLJKAJSHD']}
df1 = pd.DataFrame(d1)
df1:
letters
0 ABCDE[NOT]FGH
1 CCGF[NOT]HI
2 MPJ[NOT]L
3 MNA[NOT]PLJKAJSHD
我想在除 [ ] 之间的字符之外的每个字符之间创建一个 space。
期望的输出:
letters
0 A B C D E [NOT] F G H
1 C C G F [NOT] H I
2 M P J [NOT] L
3 M N A [NOT] P L J K A J S H D
我试过:
matching = re.sub(r'[^a-zA-Z []]+(?![^{]*})(\w)', r'', i)
df1['letters'].apply(lambda x: matching)
但这似乎不起作用。
有什么想法吗?
您可以将 space 附加到每个 [...]
子字符串或在字符串中找到的任何其他字符,然后 rstrip
结果:
>>> df1['letters'].str.replace(r'\[[^][]*]|.', r'\g<0> ', regex=True).str.rstrip()
0 A B C D E [NOT] F G H
1 C C G F [NOT] H I
2 M P J [NOT] L
3 M N A [NOT] P L J K A J S H D
Name: letters, dtype: object
参见 this regex demo。
另一种方法是在与 \[[^][]*]
模式匹配的字符以外的任何字符周围添加 spaces,然后 str.strip()
结果:
>>> df1['letters'].str.replace(r'(\[[^][]*])|.', lambda x: x.group(1) if x.group(1) else f" {x.group()} ", regex=True).str.strip()
0 A B C D E [NOT] F G H
1 C C G F [NOT] H I
2 M P J [NOT] L
3 M N A [NOT] P L J K A J S H D
Name: letters, dtype: object
(\[[^][]*])|.
正则表达式匹配并捕获到第 1 组 a [
,然后是 [
和 ]
以外的任何零个或多个字符,然后是 ]
字符,或除换行符字符以外的任何字符,如果被捕获则替换为第 1 组值,否则替换为“space”+ 匹配值 +“space”。
str.strip()
删除 leading/trailing spaces,如果替换操作产生的话。
非Pandas代码
import re
# Solution 1
text = re.sub(r'\[[^][]*]|.', r'\g<0> ', text).rstrip()
# Solution 1
text = re.sub(r'(\[[^][]*])|.', lambda x: x.group(1) if x.group(1) else f" {x.group()} ", text).strip()
尽管效率极低,但您可以使用它并避免 post-processing:
(?=(?!^)[^\[\]]*?\[|[^\[\]]+$)
(?=
- 开始前瞻
(?!^)
- 不要断言字符串的开头
[^\[\]]*?\[
- 断言导致左括号 [
的任何位置
|
- 或
[^\[\]]+$
- 断言任何不是通向行尾的括号的位置
)
- 关闭前瞻
https://regex101.com/r/zoHEne/1/
注意: regex101 示例仅由于多行而具有尾随空格。一次测试每一行以查看没有尾随空格。
您可以使用 re.findall
:
import pandas as pd, re
d1 = {'letters':['ABCDE[NOT]FGH', 'CCGF[NOT]HI', 'MPJ[NOT]L', 'MNA[NOT]PLJKAJSHD']}
df1 = pd.DataFrame(d1)
df1['letters'] = df1['letters'].apply(lambda x:' '.join(re.findall('\[\w+\]|\w', x)))
letters
0 A B C D E [NOT] F G H
1 C C G F [NOT] H I
2 M P J [NOT] L
3 M N A [NOT] P L J K A J S H D
我有一个数据框:
d1 ={'letters':['ABCDE[NOT]FGH', 'CCGF[NOT]HI', 'MPJ[NOT]L', 'MNA[NOT]PLJKAJSHD']}
df1 = pd.DataFrame(d1)
df1:
letters
0 ABCDE[NOT]FGH
1 CCGF[NOT]HI
2 MPJ[NOT]L
3 MNA[NOT]PLJKAJSHD
我想在除 [ ] 之间的字符之外的每个字符之间创建一个 space。
期望的输出:
letters
0 A B C D E [NOT] F G H
1 C C G F [NOT] H I
2 M P J [NOT] L
3 M N A [NOT] P L J K A J S H D
我试过:
matching = re.sub(r'[^a-zA-Z []]+(?![^{]*})(\w)', r'', i)
df1['letters'].apply(lambda x: matching)
但这似乎不起作用。 有什么想法吗?
您可以将 space 附加到每个 [...]
子字符串或在字符串中找到的任何其他字符,然后 rstrip
结果:
>>> df1['letters'].str.replace(r'\[[^][]*]|.', r'\g<0> ', regex=True).str.rstrip()
0 A B C D E [NOT] F G H
1 C C G F [NOT] H I
2 M P J [NOT] L
3 M N A [NOT] P L J K A J S H D
Name: letters, dtype: object
参见 this regex demo。
另一种方法是在与 \[[^][]*]
模式匹配的字符以外的任何字符周围添加 spaces,然后 str.strip()
结果:
>>> df1['letters'].str.replace(r'(\[[^][]*])|.', lambda x: x.group(1) if x.group(1) else f" {x.group()} ", regex=True).str.strip()
0 A B C D E [NOT] F G H
1 C C G F [NOT] H I
2 M P J [NOT] L
3 M N A [NOT] P L J K A J S H D
Name: letters, dtype: object
(\[[^][]*])|.
正则表达式匹配并捕获到第 1 组 a [
,然后是 [
和 ]
以外的任何零个或多个字符,然后是 ]
字符,或除换行符字符以外的任何字符,如果被捕获则替换为第 1 组值,否则替换为“space”+ 匹配值 +“space”。
str.strip()
删除 leading/trailing spaces,如果替换操作产生的话。
非Pandas代码
import re
# Solution 1
text = re.sub(r'\[[^][]*]|.', r'\g<0> ', text).rstrip()
# Solution 1
text = re.sub(r'(\[[^][]*])|.', lambda x: x.group(1) if x.group(1) else f" {x.group()} ", text).strip()
尽管效率极低,但您可以使用它并避免 post-processing:
(?=(?!^)[^\[\]]*?\[|[^\[\]]+$)
(?=
- 开始前瞻(?!^)
- 不要断言字符串的开头[^\[\]]*?\[
- 断言导致左括号[
的任何位置
|
- 或[^\[\]]+$
- 断言任何不是通向行尾的括号的位置
)
- 关闭前瞻
https://regex101.com/r/zoHEne/1/
注意: regex101 示例仅由于多行而具有尾随空格。一次测试每一行以查看没有尾随空格。
您可以使用 re.findall
:
import pandas as pd, re
d1 = {'letters':['ABCDE[NOT]FGH', 'CCGF[NOT]HI', 'MPJ[NOT]L', 'MNA[NOT]PLJKAJSHD']}
df1 = pd.DataFrame(d1)
df1['letters'] = df1['letters'].apply(lambda x:' '.join(re.findall('\[\w+\]|\w', x)))
letters
0 A B C D E [NOT] F G H
1 C C G F [NOT] H I
2 M P J [NOT] L
3 M N A [NOT] P L J K A J S H D