在Python中,如何分割一个string并保留分隔符?
这是解释这个最简单的方法。 以下是我正在使用的:
re.split('\W', 'foo/bar spam\neggs') -> ['foo', 'bar', 'spam', 'eggs']
这是我想要的:
someMethod('\W', 'foo/bar spam\neggs') -> ['foo', '/', 'bar', ' ', 'spam', '\n', 'eggs']
原因是我想把一个string拆分成令牌,操作它,然后再把它放回去。
>>> re.split('(\W)', 'foo/bar spam\neggs') ['foo', '/', 'bar', ' ', 'spam', '\n', 'eggs']
如果你正在拆分换行符,使用splitlines(True)
。
>>> 'line 1\nline 2\nline without newline'.splitlines(True) ['line 1\n', 'line 2\n', 'line without newline']
(不是一个通用的解决scheme,但在这里添加这个,以防有人来这里没有实现这个方法。)
另一个没有正则expression式的解决scheme,在Python 3上运行良好
# Split strings and keep separator test_strings = ['<Hello>', 'Hi', '<Hi> <Planet>', '<', ''] def split_and_keep(s, sep): if not s: return [''] # consistent with string.split() # Find replacement character that is not used in string # ie just use the highest available character plus one # Note: This fails if ord(max(s)) = 0x10FFFF (ValueError) p=chr(ord(max(s))+1) return s.replace(sep, sep+p).split(p) for s in test_strings: print(split_and_keep(s, '<')) # If the unicode limit is reached it will fail explicitly unicode_max_char = chr(1114111) ridiculous_string = '<Hello>'+unicode_max_char+'<World>' print(split_and_keep(ridiculous_string, '<'))
# This keeps all separators in result ########################################################################## import re st="%%(c+dd+e+f-1523)%%7" sh=re.compile('[\+\-//\*\<\>\%\(\)]') def splitStringFull(sh, st): ls=sh.split(st) lo=[] start=0 for l in ls: if not l : continue k=st.find(l) llen=len(l) if k> start: tmp= st[start:k] lo.append(tmp) lo.append(l) start = k + llen else: lo.append(l) start =llen return lo ############################# li= splitStringFull(sh , st) ['%%(', 'c', '+', 'dd', '+', 'e', '+', 'f', '-', '1523', ')%%', '7']
你也可以用一个string数组而不是一个正则expression式来分割一个string,如下所示:
def tokenizeString(aString, separators): #separators is an array of strings that are being used to split the the string. #sort separators in order of descending length separators.sort(key=len) listToReturn = [] i = 0 while i < len(aString): theSeparator = "" for current in separators: if current == aString[i:i+len(current)]: theSeparator = current if theSeparator != "": listToReturn += [theSeparator] i = i + len(theSeparator) else: if listToReturn == []: listToReturn = [""] if(listToReturn[-1] in separators): listToReturn += [""] listToReturn[-1] += aString[i] i += 1 return listToReturn print(tokenizeString(aString = "\"\"\"hi\"\"\" hello + world += (1*2+3/5) '''hi'''", separators = ["'''", '+=', '+', "/", "*", "\\'", '\\"', "-=", "-", " ", '"""', "(", ")"]))
如果你想分割string,而保持分隔符正则expression式不捕获组:
def finditer_with_separators(regex, s): matches = [] prev_end = 0 for match in regex.finditer(s): match_start = match.start() if (prev_end != 0 or match_start > 0) and match_start != prev_end: matches.append(s[prev_end:match.start()]) matches.append(match.group()) prev_end = match.end() if prev_end < len(s): matches.append(s[prev_end:]) return matches regex = re.compile(r"[\(\)]") matches = finditer_with_separators(regex, s)
如果假定正则expression式被包含进捕获组中:
def split_with_separators(regex, s): matches = list(filter(None, regex.split(s))) return matches regex = re.compile(r"([\(\)])") matches = split_with_separators(regex, s)
这两种方式也将删除在大多数情况下无用和烦人的空组。
如果你只有一个分隔符,你可以使用列表parsing:
text = 'foo,bar,baz,qux' sep = ','
附加/预先分隔符:
result = [x+sep for x in text.split(sep)] #['foo,', 'bar,', 'baz,', 'qux,'] # to get rid of trailing result[-1] = result[-1].strip(sep) #['foo,', 'bar,', 'baz,', 'qux'] result = [sep+x for x in text.split(sep)] #[',foo', ',bar', ',baz', ',qux'] # to get rid of trailing result[0] = result[0].strip(sep) #['foo', ',bar', ',baz', ',qux']
分隔符是它自己的元素:
result = [u for x in text.split(sep) for u in (x, sep)] #['foo', ',', 'bar', ',', 'baz', ',', 'qux', ','] results = result[:-1] # to get rid of trailing