How can I remove numbers, and words with length below 2, from a sentence?

Viewed 630

I am trying to remove words that have length below 2 and any word that is numbers. For example

 s = " This is a test 1212 test2"

Output desired is

" This is test test2"

I tried \w{2,} this removes all the word whose length is below 2. When I added \D+ this removes all numbers when I didn't want to get rid of 2 from test2.

5 Answers

You may use:

s = re.sub(r'\b(?:\d+|\w)\b\s*', '', s)

RegEx Demo

Pattern Details:

  • \b: Match word boundary
  • (?:\d+|\w): Match a single word character or 1+ digits
  • \b: Match word boundary
  • \s*: Match 0 or more whitespaces

You can make use of work boundaries '\b' and remove anything that is 1 character long inside boundaries: number or letter, doesn't matter. Also remove anything between boundaries that is just numbers:

import re

s = " This is a test 1212 test2"

print( re.sub(r"\b([^ ]|\d+)\b","",s))

Output:

 This is  test  test2

Explanation:

\b(           word boundary followed by a group
   [^ ]           anything that is not a space (1 character) 
       |              or
        \d+       any amount of numbers
)             followed by another boundary

is replaced by re.sub(pattern, replaceBy, source) with "".

Maybe (?i)\b(?:\d+|[a-z])\b[ \t]*
https://regex101.com/r/bnS15k/1

Does some wsp trimming.


Whitespace trimming is probably more important for these kind of things.
This modded version does it from both sides.

Just subs it using
(?im)(?:([ \t])+\b(?:\d+|[a-z])\b[ \t]*[ \t]*|^\b(?:\d+|[a-z])\b[ \t]*[ \t]*())
With replace \1\2

https://regex101.com/r/gSswPe/1
Strips wsp from both sides.

 (?im)
 (?:
    ( [ \t] )+           # (1)
    \b 
    (?: \d+ | [a-z] )
    \b [ \t]* [ \t]* 
  | 
    ^ \b 
    (?: \d+ | [a-z] )
    \b [ \t]* [ \t]* 
    ( )                  # (2)
 )

You can do it like that:

import re

s = " This is a test 1212 test2"

p = re.compile(r"(\b(\w{0,1})\b)|(\b(\d+)\b)")

result = p.sub('', s)

print(result)

Output:

" This is  test  test2"

I noticed that your desired output does not contain consecutive whitespaces. If you want to replace consecutive whitespaces by one, you can do this:

p = re.compile(r"  +")
result = p.sub(' ', result)

Output:

" This is test test2"

(\b(\w{0,1})\b) this group matches words with length up to 1 (included)

(\b(\d+)\b) this group matches word composed of digit(s) only

| The pipe means "or", so this expression will match either group 1 or group 2

\b It's the "word boundary". By surrounding some regex with "\b", it will match "whole words only"

\w It will match wharacters supposed to part of a word

\d+ This means "at least one digit or more"

Note that what \b and \w will match will depends on the regex flavor you are using.

Just to put my two cents in - you could use the inbuilt string functions:

s = " This is a test 1212 test2"
result = " ".join(word for word in s.split() 
                  if len(word) >= 2 and not word.isdigit())
print(result)

Which would yield

This is test test2
Related