用多个分隔符分割一个字符串,并保留*一些*的分隔符,但不是全部

时间:2021-01-13 11:39:12

标签: python python-3.x regex

我有一个看起来像这样的字符串:

1. "foo bar"
2. "foo bar foo:bar"
3. "foo bar "
4. "foo bar      "
5. "foo bar foo:bar:baz"

我想拆分这个字符串,以便得到以下结果:

1. ['foo', 'bar']
2. ['foo', 'bar', 'foo', ':', 'bar']
3. / 4. ['foo', 'bar', '']
5. ['foo', 'bar', 'foo', ':', 'bar', ':', 'baz']

换句话说,遵循以下规则:

  1. 在每次出现空格时分割字符串。

    一个。如果字符串末尾有一个或多个空格,则在拆分列表中添加一个空字符串

    B.字符串中最后一个非空格字符之前的任何空格都应该被消耗掉,而不是添加到拆分列表中。

  2. 在每次出现冒号时拆分字符串,并且不要消耗冒号。

XY 问题是这样的,以防万一:

我想模仿 Bash 选项卡完成行为。当您在 Bash 解释器中键入命令时,它会将命令拆分为数组 COMP_WORDS,并且它将遵循上述规则 - 基于空格和冒号拆分单词,将冒号放入其自己的数组元素中,和空格被忽略,除非它们位于字符串的末尾。我想在 Python 中重新创建这种行为,给定一个字符串,该字符串看起来像用户会键入的命令。

我已经看到 this question 关于使用 re.split 拆分字符串并保留分隔符。和 this question 关于使用多个分隔符进行拆分。但我的用例更复杂,似乎没有一个问题涵盖它。我尝试了以下至少在空格和冒号上拆分:

print(re.split('(:)|(?: )', splitstr))

但即使这样也行不通。当 splitstr 为 "foo bar foo:bar" 时返回:

['foo', None, 'bar', None, 'foo', ':', 'bar']

知道如何在 Python 中做到这一点吗?

编辑:我的要求不清楚 - 我希望“foo bar”(末尾有任意数量的空格)返回列表 ["foo", "bar", ""](只有一个空列表末尾的字符串。)

1 个答案:

答案 0 :(得分:1)

您可以在此处使用 re.findall 方法:

[^:\s]+|:|(?<=\S)(?=\s+$)

参见regex demo详情

  • [^:\s]+ - 除了空格和 :
  • 之外的一个或多个字符
  • | - 或
  • : - 一个冒号
  • | - 或
  • (?<=\S)(?=\s+$) - 位于非空格和字符串末尾的一个或多个空格之间的任何空字符串。

参见Python demo

import re
l = ['foo bar', 'foo bar foo:bar', 'foo bar ', 'foo     bar     ']
rx = re.compile(r'[^:\s]+|:|(?<=\S)(?=\s+$)')
for s in l:
    if s.rstrip() != s:
        s = s.rstrip() + " "
    print(f"'{s}'", '=>', rx.findall(s))

输出:

'foo bar' => ['foo', 'bar']
'foo bar foo:bar' => ['foo', 'bar', 'foo', ':', 'bar']
'foo bar ' => ['foo', 'bar', '']
'foo     bar ' => ['foo', 'bar', '']
相关问题