Do you need a regex? You can do something like
>>> words = "ABCD abcd AB55 55CD A55D 5555"
>>> ' '.join(s for s in words.split() if not any(c.isdigit() for c in s))
'ABCD abcd'
If you really want to use regex, you can try \w*\d\w*:
>>> re.sub(r'\w*\d\w*', '', words).strip()
'ABCD abcd'
Answer from arshajii on Stack OverflowDo you need a regex? You can do something like
>>> words = "ABCD abcd AB55 55CD A55D 5555"
>>> ' '.join(s for s in words.split() if not any(c.isdigit() for c in s))
'ABCD abcd'
If you really want to use regex, you can try \w*\d\w*:
>>> re.sub(r'\w*\d\w*', '', words).strip()
'ABCD abcd'
Here's my approach:
>>> import re
>>> s = "ABCD abcd AB55 55CD A55D 5555"
>>> re.sub("\S*\d\S*", "", s).strip()
'ABCD abcd'
>>>
You can use this regex:
>>> s = "12 word word2"
>>> print re.sub(r'\b[0-9]+\b\s*', '', s)
word word2
\b is used for word boundary and \s* will remove 0 or more spaces after your number word.
Using a regex is probably a bit overkill here depending whether you need to preserve whitespace:
s = "12 word word2"
s2 = ' '.join(word for word in s.split() if not word.isdigit())
# 'word word2'
Your method seems ok, but if you want to use a regex (like the tag suggests) you can use this to capture all the characters that are not lower/uppercase letters or spaces:
[^a-zA-Z ]*
Then you can replace with an empty string.
import re
input_text = "This is a test number +223/34 and this a real number 2333."
clean_text=re.sub("[^a-zA-Z ]*", "", input_text)
You can simply check if a token is alphanumeric:
clean_text = " ".join([word for word in input_text.split() if word.isalnum()])
See a Python demo:
input_text = 'This is a test number +223/34 and this a real number 2333.'
print( " ".join([word for word in input_text.split() if word.isalnum()]) )
# => This is a test number and this a real number
If you have specific patterns in mind, you can write specific regex patterns to find the matching strings and delete them with re.sub. For example, if you want to remove standalone numbers that can contain match operators between them, or dots/commas, you can use the following:
import re
input_text = 'This is a test number +223/34 and this a real number 2333. The email is [email protected] and the website is www.test.com.'
print( re.sub(r'[-+]?\b\d+(?:[.,+/*-]\d+)*\b', '', input_text) )
that yields the expected:
This is a test number and this a real number . The email is [email protected] and the website is www.test.com.
See the Python demo. The regex means
[-+]?- an optional+or-\b- a word boundary (the digit cannot be glued to a word)\d+- one or more digits(?:[.,+/*-]\d+)*- zero or more repetitions of./,/+,/,*,-and then one or more digits\b- a word boundary (the digit cannot be glued to a word).
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 "".
Would this work for your situation?
>>> s = '12abcd405'
>>> result = ''.join([i for i in s if not i.isdigit()])
>>> result
'abcd'
This makes use of a list comprehension, and what is happening here is similar to this structure:
no_digits = []
# Iterate through the string, adding non-numbers to the no_digits list
for i in s:
if not i.isdigit():
no_digits.append(i)
# Now join all elements of the list with '',
# which puts all of the characters together.
result = ''.join(no_digits)
As @AshwiniChaudhary and @KirkStrauser point out, you actually do not need to use the brackets in the one-liner, making the piece inside the parentheses a generator expression (more efficient than a list comprehension). Even if this doesn't fit the requirements for your assignment, it is something you should read about eventually :) :
>>> s = '12abcd405'
>>> result = ''.join(i for i in s if not i.isdigit())
>>> result
'abcd'
And, just to throw it in the mix, is the oft-forgotten str.translate which will work a lot faster than looping/regular expressions:
For Python 2:
from string import digits
s = 'abc123def456ghi789zero0'
res = s.translate(None, digits)
# 'abcdefghizero'
For Python 3:
from string import digits
s = 'abc123def456ghi789zero0'
remove_digits = str.maketrans('', '', digits)
res = s.translate(remove_digits)
# 'abcdefghizero'
I'm not sure exactly what you want here, but it seems you want to remove words that have a digit in them. In that case, you can use any() here:
>>> c = "Snap-on Power M1302A5 Imperial,IMPRL 0.062IN"
>>> ' '.join(w for w in c.split() if not any(x.isdigit() for x in w))
Snap-on Power Imperial,IMPRL
Also adding a regex based solution:
c = "Snap-on Power M1302A5 Imperial,IMPRL 0.062IN"
only_a = []
for word in c.split():
#print(word)
if not re.search('\d',word):
#print(word)
only_a.append(word)
' '.join(only_a)
Output: 'Snap-on Power Imperial,IMPRL'
Without regex:
[x for x in my_list if not any(c.isdigit() for c in x)]
I find using isalpha() the most elegant, but it will also remove items that contain other non-alphabetic characters:
Return true if all characters in the string are alphabetic and there is at least one character, false otherwise. Alphabetic characters are those characters defined in the Unicode character database as “Letter”
my_list = [item for item in my_list if item.isalpha()]
You might also use a capturing group capturing only a single char before matching 1+ digits.
In the replacement using group 1 using \1
([a-z])\d+\b
regex demo
import re
text ='Senku Ishigami is charecter from a manga series98 onging since 2017.'
text = re.sub(r'([a-z])\d+\b', r'\1', text)
print(text)
Output
Senku Ishigami is charecter from a manga series onging since 2017.
You can use
import re
text ='Senku Ishigami is charecter from a manga series98 onging since 2017.'
text = re.sub(r'(?<=[a-z])\d+\b', '', text)
print(text) # => Senku Ishigami is charecter from a manga series onging since 2017.
See the regex demo and a Python demo.
Regex details
(?<=[a-z])- a location immediately preceded with a lowercase ASCII letter\d+- one or more digits\b- word boundary (the digits will only be matched at the end of a word).
You can use this regex to match the strings you want to remove:
(?:^|\s)[0-9]+\.[0-9.]*(?=\s|$)
It matches:
(?:^|\s): beginning of string or whitespace[0-9]+: at least one digit\.: a period[0-9.]*: some number of digits and periods(?=\s|$): a lookahead to assert end of string or whitespace
Regex demo
You can then replace any matches with the empty string. In python
this_string = 'lorum3 ipsum 15.2.3.9.7 bar foo 1. v more text 46 2. here and even more text here v7.8.989 and also 1.2.3c as well'
result = re.sub(r'(?:^|\s)[0-9]+\.[0-9.]*(?=\s|$)', '', this_string)
Output:
lorum3 ipsum bar foo v more text 46 here and even more text here v7.8.989 and also 1.2.3c as well
If you can make use of a lookbehind, you can match the numbers and replace with an empty string:
(?<!\S)\d+\.[\d.]*(?!\S)
Explanation
(?<!\S)Assert a whitespace boundary to the left\d+\.[\d.]*Match 1+ digits, then a dot followed by optional digits or dots(?!\S)Assert a whitespace boundary to the right
Regex demo
If you want to match an optional leading whitespace char:
\s?(?<!\S)\d+\.[\d.]*(?!\S)
Regex demo