2
\$\begingroup\$

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   
\$\endgroup\$
7
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ 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). \$\endgroup\$ – Pryftan Jun 18 at 14:53
6
\$\begingroup\$

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 ==.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.