如何在Python中将字符串内的多个空格替换为单个空格,但不替换开头的多个空格?

3

我有一些字符串可能有多个前导空格。

string_1 = '    param A     val A'
string_2 = 'param B    val B'

....

我希望将所有不在字符串开头的连续空格替换为单个空格。
我希望输出结果如下:
 string_1 = '    param A val A'z
 string_2 = 'param B val B'

我的当前解决方案会替换所有多个空格为单个空格。

 re.sub('\s+',' ',s)

如何构建只捕获非首位多个空格的模式?

3个回答

5
您可以使用\b\s{2,}\b作为您的模式,如果这些多个空格是前导空格,则它们不在单词边界内。此外,对于多个空格,请使用{2,}代替+来排除单个空格:
import re


string_1 = "    param A     val A"
string_2 = "param B    val B"


pattern = re.compile(r"\b\s{2,}\b")
for test in (string_1, string_2):
    print(pattern.sub(" ", test))

输出:

    param A val A
param B val B

注意: 后面多个空格不会被这种方式改变。如果要处理可以省略最后的\b,那么再次转换为单个空格。


如@JvdV所述,\b 不考虑其他范围内的字符。例如,如果您有一个类似"[ param A val A ]"的字符串,则上面的模式将无法匹配它。相反,您可以使用 正向截断断言((?<=\S)) 和 正向预查断言 ((?=\S))来匹配任何非空白字符:

>>> import re
>>> text = "[    param A     val A    ]"
>>> re.sub(r"\b\s{2,}\b", " ", text)
'[    param A val A    ]'
>>> re.sub(r"(?<=\S)\s{2,}(?=\S)", " ", text)
'[ param A val A ]'

1
但是需要注意的是:\b 只能识别 \w 以外的字符。 - JvdV
1
@JvdV 谢谢提醒,已经进行了更新。 - S.B
1
完全不应该有 (?=\S) 断言,因为 OP 没有说尾随空格不应该被替换。{2,} 是贪婪的,所以 (?<=\S)\s{2,} 就可以了。 - blhsing

3

尝试一下:

(?<=\S)\s+(\s\S|$)

将其替换为\1。请查看在线演示


  • (?<=\S) - 断言位置位于非空白字符之前;
  • \s+ - 匹配 1 个或多个空白字符 (贪婪匹配);
  • (\s\S|$) - 捕获组,用于匹配一个空格字符和一个非空白字符或者字符串末尾锚点。

上面的正则表达式仅保留前导空格。例如:

import regex as re
s = '    Abc   12$   D   Efg    '
print(re.sub(r'(?<=\S)\s+(\s\S|$)', '\1', s))

输出: Abc 12$ D Efg


0

将输入分成两组(第一组:前导空格,第二组:其他所有内容),然后从第二组中消除多余的空格,并将两组合并:

>>> string_1 = '    param A     val A'
>>> sb = re.compile(r'^(\s+)(.*)')
>>> mg = sb.match(string_1).groups()
>>> mg[0] + ' '.join(mg[1].split())
'    param A val A'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接