# Regex version of strip() - Ch. 7 Automate the Boring Stuff

Here is a practice exercise — Regex version of strip() $$\-\$$

Write a function that takes a string and does the same thing as the strip() string method. If no other arguments are passed other than the string to strip, then whitespace characters will be removed from the beginning and end of the string. Otherwise, the characters specified in the second argument to the function will be removed from the string.

I have written the following code. Is there any better way to write it? Any feedback is highly appreciated.

import re

def regex_strip(s, chars = None):

if chars == None:
strip_left = re.compile(r'^\s*')
strip_right = re.compile(r'\s*$') s = re.sub(strip_left, "", s) s = re.sub(strip_right, "", s) else: strip_left = re.compile(r'^[' + re.escape(chars) + r']*') strip_right = re.compile(r'[' + re.escape(chars) + r']*$')
s = re.sub(strip_left, "", s)
s = re.sub(strip_right, "", s)
return s


Here is an example output -

s = '.*    alphabetatheta   *4453   +-'
print(regex_strip(s, '.+-*'))

>>>    alphabetatheta      *4453


## 3 Answers

If you call regex_strip(s, ""), you will get:

re.error: unterminated character set at position 0

because neither ^[] nor []$ is a valid regular expression. You could avoid this by using if not chars: instead of if chars == None:. There is no need to re.compile() your regular expressions; you aren't saving the compiled patterns anywhere for re-use. You can simplify your logic by using the reg-ex to capture the middle, non-stripped portion of the string, instead of doing two replacements for the start and end trim operations: import re def regex_strip(s, chars = None): if chars: trim = '[' + re.escape(chars) + ']*' else: trim = r'\s*' return re.fullmatch(f"{trim}(.*?){trim}", s).group(1)  I'm not sure the point of asking you to write your own strip() function is to delegate the task to the reg-ex engine. It seems like going out and buying a sledge hammer when the problem is to build a nut cracker. • Maybe something of value to some on the subject of regex: regular-expressions.info ; also the man page regex(7) (which is less detailed but still maybe of value; there is of course also regex(3) but that's for C). – Pryftan Jun 18 '19 at 14:53 DRY. Both branches do identical re.subs. Take them out: if chars is None: strip_left = re.compile(r'^\s*') strip_right = re.compile(r'\s*$')
else:
strip_left = re.compile(r'^[' + re.escape(chars) + r']*')
strip_right = re.compile(r'[' + re.escape(chars) + r']*$') s = re.sub(strip_left, "", s) s = re.sub(strip_right, "", s) return s  I recommend to go one step further, and unify the computation of strip_*: if chars is None: chars = string.whitespace strip_left = re.compile(r'^[' + re.escape(chars) + r']*') strip_right = re.compile(r'[' + re.escape(chars) + r']*$')
s = re.sub(strip_left, "", s)
s = re.sub(strip_right, "", s)
return s


It is recommended to compare against None as chars is None rather than using ==.

I've just finished this part of the book and thought that somebody else may benefit from seeing how I've worked it out:

import re

def strip_function(text, char=' '):
chars = [letter for letter in char]
regex = re.sub(rf'^{chars}+|{chars}+$', '', text) return regex string = " strip me!ccc" print(strip_function(string, ''))  • Welcome to Code Review! Unfortunately, this doesn't quite work. While it does strip every character in char, it also strips ', , and space if more than one character is supplied due to the fact that you pass a list representation (i.e. strip_function("', abca", "ab") gives back just "c"). Just have rf'^[{char}]+|[{char}]+$' instead. – Graipher May 14 at 7:56
• Also, we expect every answer here to have at least one insight on the OP's code. Alternate solutions are not enough on their own, unless they explain how and why they are better. Have a look at our help-center for more information. – Graipher May 14 at 8:01