删除字符串的前X个单词和分隔符 - 具有多个分隔符

时间:2016-03-09 11:23:42

标签: python regex string split

我有一个字符串,例如manipulate widgets add,1,2,3(抱歉,但我无法更改格式)。

我想删除前X个单词以及预先他们的任何分隔符。

我们以3为例,删除manipulate widgets add并离开,1,2,3

或者,manipulate,widgets,add,1,2,3删除两个字(manipulate,widgets)并离开,add,1,2,3

我可以将字符串拆分为words = re.split('[' + delimiters + ']',inputString.strip())的列表,但我不能简单地删除第一个X字

,比方说,

for i in range(1, numWorsdToRemove):
            del words[0]

然后return ' '.join(words),因为它给了我1 2 3 4

我该怎么做并保留未删除单词的原始分隔符?

为了让它变得有趣,输入字符串可以在单词之间包含多个空格或制表符;只有一个逗号,但可能还有空格/取消它:

manipulate ,widgets add , 1, 2 , 3

请注意,单词不能保证是唯一的,所以我不能删除那些单词的索引,并使用它来返回位置子串。

[更新]我接受了'Kasramvd解决方案,但后来发现它没有正确处理remover('LET FOUR = 2 + 2', 2)remover('A -1 B text.txt', 2),所以现在我提供了解决方案。

[Update ++]分隔符是空格,制表符和逗号。其他所有内容(包括等号,减号等)都​​是一个单词的一部分(虽然如果有问题的话,我会很高兴,如果有必要的话会告诉我将来如何添加新的分隔符)

8 个答案:

答案 0 :(得分:2)

您可以像这样定义一个RegEx

>>> import re
>>> regEx = re.compile(r'(\s*,?\s*)')

这意味着,一个可选的逗号后跟或前面有零个或多个空白字符。括号是创建一个匹配组,它将在拆分期间保留分隔符。

现在基于RegEx进行拆分,然后跳过您不想要的实际元素数量,以及与这些元素对应的分隔符数量(例如,如果您想跳过三个元素,那么将会是三个元素之间的两个分隔符。所以你想要从分割数据中删除前五个元素)并最终加入它们。

例如,

>>> def splitter(data, count):
...     return "".join(re.split(regEx, data)[count + (count - 1):])
... 
>>> splitter("manipulate,widgets,add,1,2,3", 2)
',add,1,2,3'
>>> splitter("manipulate widgets add,1,2,3", 3)
',1,2,3'

答案 1 :(得分:2)

s1='manipulate widgets add,1,2,3'
# output desired ',1,2,3'
s2='manipulate,widgets,add,1,2,3'
# delete two words (manipulate,widgets) and leave ,add,1,2,3
s3='manipulate  ,widgets     add ,  1, 2  ,    3'
# delete 2 or 3 words

import re

# for illustration 
print re.findall('\w+',s1)
print re.findall('\w+',s2)
print re.findall('\w+',s3)
print


def deletewords(s,n):
    a= re.findall('\w+',s)
    return ','.join(a[n:])

# examples for use    
print deletewords(s1,1)   
print deletewords(s2,2)    
print deletewords(s3,3) 

输出:

['manipulate', 'widgets', 'add', '1', '2', '3']
['manipulate', 'widgets', 'add', '1', '2', '3']
['manipulate', 'widgets', 'add', '1', '2', '3']

widgets,add,1,2,3
add,1,2,3
1,2,3

答案 2 :(得分:1)

以下方法如何:

from itertools import islice
import re

text = "manipulate widgets,.  add,1,2,3"

for x in islice(re.finditer(r'\b(\w+?)\b', text), 2, 3):
    print text[x.end():]

这将显示:

,1,2,3        

答案 3 :(得分:1)

您可以使用re.sub()

>>> def remover(s, n):
...     return re.sub(r'^(\s?\b\w+\b\s?){%s}'%n,'', s)

样本:

>>> remover(s,3)
',1,2,3'
>>> remover(s,2)
'add,1,2,3'
>>> remover(s,1)
'widgets add,1,2,3'
>>> remover(s,0)
'manipulate widgets add,1,2,3'

答案 4 :(得分:1)

@original海报。请编辑测试用例,因为您的某些陈述似乎是矛盾的。您的第二个测试用例将逗号视为分隔符。但它也留下了逗号,这是第二个问题。它是一个分隔符,也可能不是。

    # testcases  : string , #of words to remove, desired answer
s=['manipulate widgets add,1,2,3',
   'manipulate,widgets,add,1,2,3',
   'manipulate  ,widgets     add ,  1, 2  ,    3',
   'manipulate  ,widgets     add ,  1, 2  ,    3',
   'LET X = 42',
   'LET FOUR = 2 + 2',
   'LET FOUR = 2 + 2',
   'A -1 B text.txt'']

X= [3,2,2,3,3,2,3,2]   

a= [',1,2,3',
    'add,1,2, 3',
    'add ,  1, 2  ,    3',
    ',  1, 2  ,    3',
    '42',
    '= 2 +2',
    '2 +2',
    'B text.txt']

#Just to make it interesting, the input string can contain multiple spaces or tabs between words;
#only one comma, but that might also have spaces pre/suc-ceeding it    
# <-- does that make the comma a word? 

# only delimiters are space and tab, not commas      
# <-- **does that make a single standing comma a word? **
# **2nd test case is contradictory to later statements, as comma is a delimiter here!**

答案 5 :(得分:1)

这似乎适用于您的测试用例:

>>> def remover(line, words):
...   parsed = re.split('(\s*,{0,1}\s*)', line, maxsplit=words)
...   return ''.join(parsed[-2:]).lstrip()
... 
>>> remover('LET FOUR = 2 + 2', 2)
'= 2 + 2'
>>> remover('A -1 B text.txt', 2)
'B text.txt'
>>> remover('manipulate widgets add,1,2,3', 3)
',1,2,3'
>>> remover('manipulate,widgets,add,1,2,3', 2)
',add,1,2,3'
>>> remover('manipulate  ,widgets     add ,  1, 2  ,    3', 2)
'add ,  1, 2  ,    3'

如果与领先的空白有什么关系,那我就不清楚了。如果应该保留,则可以删除lstrip()

答案 6 :(得分:1)

我认为这种方法非常简单,并且不使用正则表达式:

def delete_leading_words(string, num_words, delimeters=' \t,'):
    if num_words == 0:
        return string

    i = 0
    while i < len(string) and string[i] in delimeters:
        i += 1
    while i < len(string) and string[i] not in delimeters:
        i += 1

    return delete_leading_words(string[i:], num_words-1, delimeters)

答案 7 :(得分:0)

很难确定您对“分隔符”和“单词”的定义是什么。例如,在A -1 B text.txt情况下,-1是否应被视为单词,或者是否应将字符串视为没有要删除的单词。这可以使用Kasramvd提供的正则表达式轻松定制。例如,如果你认为-1是一个“单词”,那么这基本上就是诀窍:

import re


def remover(s, n):
    return re.sub(r'^(\s?\s*[^\s]+\s?){%s}' % n, '', s)

s = 'manipulate widgets add,1,2,3'

print('\nString is: {}\n'.format(s))
[print('Remove {}: '.format(x), remover(s, x)) for x in range(4)]

s = 'LET FOUR = 2 + 2 '

print('\nString is: {}\n', s)
[print('Remove {}: '.format(x), remover(s, x)) for x in range(7)]

s = 'A -1 B C text.txt'

print('\nString is: {}\n', s)
[print('Remove {}: '.format(x), remover(s, x)) for x in range(6)]

产生:

String is: manipulate widgets add,1,2,3

Remove 0:  manipulate widgets add,1,2,3
Remove 1:  widgets add,1,2,3
Remove 2:  add,1,2,3
Remove 3:  

String is: {}
 LET FOUR = 2 + 2 
Remove 0:  LET FOUR = 2 + 2 
Remove 1:  FOUR = 2 + 2 
Remove 2:  = 2 + 2 
Remove 3:  2 + 2 
Remove 4:  + 2 
Remove 5:  2 
Remove 6:  

String is: {}
 A -1 B C text.txt
Remove 0:  A -1 B C text.txt
Remove 1:  -1 B C text.txt
Remove 2:  B C text.txt
Remove 3:  C text.txt
Remove 4:  text.txt
Remove 5:  

但是=呢? =应该是“单词”还是“分隔符”或什么?如果规则不同,请告诉我们规则究竟是什么。