I am trying to replace all the hyphenated words in string with their separated versions. I am able to detect hyphenated words but I could not replace them with seperate versions. How can I do that?
This is the example and a sample code :
import re
text = "one-hundered-and-three- some text foo-bar some--text"
re.findall(r'\w+(?:-\w+)+',text)
# returns: ['one-hundered-and-three', 'foo-bar']
# I want to modify text as follows:
# text_new = "one hundered and three- some text foo bar some--text"
re.sub() with positive lookahead and lookbehind:
import re
text = "one-hundered-and-three- some text foo-bar some--text"
print(re.sub(r'(?<=\w)-(?=\w)', ' ', text))
# one hundered and three- some text foo bar some--text
You can use a really simple pattern:
\b-\b
\b Word boundary.
- Hyphen.
\b Word boundary.
Regex demo here.
Python demo:
import re
text = "one-hundered-and-three- some text foo-bar some--text"
print(re.sub(r'\b-\b', ' ', text))
Prints:
one hundered and three- some text foo bar some--text
You could use re.sub() with a function for the repl argument:
In [12]: re.sub(r'\w+(?:-\w+)+', lambda match: match.group(0).replace('-', ' '), text)
Out[12]: 'one hundered and three- some text foo bar some--text'
I wrote it as a one-liner here, but I think it would be clearer if the lambda were moved out into a named function.
Related
Basically, I want to drop all the dots in the abbreviations like "L.L.C.", converting to "LLC". I don't have a list of all the abbreviations. I want to convert them as they are found. This step is performed before sentence tokenization.
text = """
Proligo L.L.C. is a limited liability company.
S.A. is a place.
She works for AAA L.P. in somewhere.
"""
text = re.sub(r"(?:([A-Z])\.){2,}", "\1", text)
This does not work.
I want to remove the dots from the abbreviations so that the dots will not break the sentence tokenizer.
Thank you!
P.S. Sorry for not being clear enough. I edited the sample text.
Try using a callback function with re.sub:
def callback( str ):
return str.replace('.', '')
text = "L.L.C., S.A., L.P."
text = re.sub(r"(?:[A-Z]\.)+", lambda m: callback(m.group()), text)
print(text)
The regex pattern (?:[A-Z]\.)+ will match any number of capital abbreviations. Then, for each match, the callback function will strip off dots.
import re
string = 'ha.f.d.s.a.s.d.f'
re.sub('\.', '', string)
#output
hafdsasdf
Note that this only works properly if your text does not contain multiple sentences. If it does it will create one long sentence as all '.' are replaced.
Use this regular expression:
>>> re.sub(r"(?<=[A-Z]).", "", text)
'LLC, SA, LP'
>>>
regex101
The answers here are extremely aggressive: any capital alphabetical character followed by a period will be replaced.
I'd recommend:
text = "L.L.C., S.A., L.P."
text = re.sub(r"L\.L\.C\.|S\.A\.|L\.P\.", lambda x: x.group().replace(".", ""), text)
print(text) # => "LLC, SA, LP"
This will only match the abbreviations you're asking for. You can add word boundaries for additional strictness.
I'm looking to grab noise text that has a specific pattern in it:
text = "this is some text lskdfmd&#kjansdl and some more text sldkf&#lsakjd and some other stuff"
I want to be able to remove everything in this sentence where after a space, and before a space contains &#.
result = "this is some text and some more text and some other stuff"
been trying:
re.compile(r'([\s]&#.*?([\s])).sub(" ", text)
I can't seem to get the first part though.
You may use
\S+&#\S+\s*
See a demo on regex101.com.
In Python:
import re
text = "this is some text lskdfmd&#kjansdl and some more text sldkf&#lsakjd and some other stuff"
rx = re.compile(r'\S+&#\S+\s*')
text = rx.sub('', text)
print(text)
Which yields
this is some text and some more text and some other stuff
You can use this regex to capture that noise string,
\s+\S*&#\S*\s+
and replace it with a single space.
Here, \s+ matches any whitespace(s) then \S* matches zero or more non-whitespace characters while sandwiching &# within it and again \S* matches zero or more whitespace(s) and finally followed by \s+ one or more whitespace which gets removed by a space, giving you your intended string.
Also, if this noise string can be either at the very start or very end of string, feel free to change \s+ to \s*
Regex Demo
Python code,
import re
s = 'this is some text lskdfmd&#kjansdl and some more text sldkf&#lsakjd and some other stuff'
print(re.sub(r'\s+\S*&#\S*\s+', ' ', s))
Prints,
this is some text and some more text and some other stuff
Try This:
import re
result = re.findall(r"[a-zA-z]+\&\#[a-zA-z]+", text)
print(result)
['lskdfmd&#kjansdl', 'sldkf&#lsakjd']
now remove the result list from the list of all words.
Edit1 Suggest by #Jan
re.sub(r"[a-zA-z]+\&\#[a-zA-z]+", '', text)
output: 'this is some text and some more text and some other stuff'
Edit2 Suggested by #Pushpesh Kumar Rajwanshi
re.sub(r" [a-zA-z]+\&\#[a-zA-z]+ ", " ", text)
output:'this is some text and some more text and some other stuff'
How can I put in brackets / parenthesis some words following another word in python?
For 2 words it looks like:
>>> p=re.compile(r"foo\s(\w+)\s(\w+)")
>>> p.sub( r"[\1] [\2]", "foo bar baz")
'[bar] [baz]'
I want for undefined number of words. I came up with this, but it doesn't seem to work.
>>> p=re.compile(r"foo(\s(\w+))*")
>>> p.sub( r"[\2] [\2] [\2]", "foo bar baz bax")
'[bax] [bax] [bax]'
The desired result in this case would be
'[bar] [baz] [bax]'
You may use a solution like
import re
p = re.compile(r"(foo\s+)([\w\s]+)")
r = re.compile(r"\w+")
s = "foo bar baz"
print( p.sub( lambda x: "{}{}".format(x.group(1), r.sub(r"[\g<0>]", x.group(2))), s) )
See the Python demo
The first (foo\s+)([\w\s]+) pattern matches and captures foo followed with 1+ whitespaces into Group 1 and then captures 1+ word and whitespace chars into Group 2.
Then, inside the re.sub, the replacement argument is a lambda expression where all 1+ word chunks are wrapped with square brackets using the second simple \w+ regex (that is done to ensure the same amount of whitespaces between the words, else, it can be done without a regex).
Note that [\g<0>] replacement pattern inserts [, the whole match value (\g<0>) and then ].
I suggest you the following simple solution:
import re
s = "foo bar baz bu bi porte"
p = re.compile(r"foo\s([\w\s]+)")
p = p.match(s)
# Here: p.group(1) is "bar baz bu bi porte"
# p.group(1).split is ['bar', 'baz' ,'bu' ,'bi', 'porte']
print(' '.join([f'[{i}]' for i in p.group(1).split()])) # for Python 3.6+ (due to f-strings)
# [bar] [baz] [bu] [bi] [porte]
print(' '.join(['[' + i + ']' for i in p.group(1).split()])) # for other Python versions
# [bar] [baz] [bu] [bi] [porte]
String two-part fixed and separated by a space
import re
text="jahir islam"
print(re.sub(r' ',text))
Input: jahir islam
Output: islam jahir
You don't need to do that. Just split the string on the space and reverse it and join it back;
input_str = "jahir islam"
output_str = " ".join(input_str.split(" ")[::-1])
Using regex you can do this way if you know that you have only 2 words you need to swap
import re
text = 'jahir islam'
print re.sub(r'(.*) (.*)', r'\2 \1', text)
explanation:
re.sub(r'(.*) (.*)', r'\2 \1', text)
it groups the words and '\1' and '\2' are the representation of the groups you made, now you can place them any where as you want
for further query you can post a comment
Lets say I have:
a = r''' Example
This is a very annoying string
that takes up multiple lines
and h#s a// kind{s} of stupid symbols in it
ok String'''
I need a way to do a replace(or just delete) and text in between "This" and "ok" so that when I call it, a now equals:
a = "Example String"
I can't find any wildcards that seem to work. Any help is much appreciated.
You need Regular Expression:
>>> import re
>>> re.sub('\nThis.*?ok','',a, flags=re.DOTALL)
' Example String'
Another method is to use string splits:
def replaceTextBetween(originalText, delimeterA, delimterB, replacementText):
leadingText = originalText.split(delimeterA)[0]
trailingText = originalText.split(delimterB)[1]
return leadingText + delimeterA + replacementText + delimterB + trailingText
Limitations:
Does not check if the delimiters exist
Assumes that there are no duplicate delimiters
Assumes that delimiters are in correct order
The DOTALL flag is the key. Ordinarily, the '.' character doesn't match newlines, so you don't match across lines in a string. If you set the DOTALL flag, re will match '.*' across as many lines as it needs to.
Use re.sub : It replaces the text between two characters or symbols or strings with desired character or symbol or string.
format: re.sub('A?(.*?)B', P, Q, flags=re.DOTALL)
where
A : character or symbol or string
B : character or symbol or string
P : character or symbol or string which replaces the text between A and B
Q : input string
re.DOTALL : to match across all lines
import re
re.sub('\nThis?(.*?)ok', '', a, flags=re.DOTALL)
output : ' Example String'
Lets see an example with html code as input
input_string = '''<body> <h1>Heading</h1> <p>Paragraph</p><b>bold text</b></body>'''
Target : remove <p> tag
re.sub('<p>?(.*?)</p>', '', input_string, flags=re.DOTALL)
output : '<body> <h1>Heading</h1> <b>bold text</b></body>'
Target : replace <p> tag with word : test
re.sub('<p>?(.*?)</p>', 'test', input_string, flags=re.DOTALL)
otput : '<body> <h1>Heading</h1> test<b>bold text</b></body>'
a=re.sub('This.*ok','',a,flags=re.DOTALL)
If you want first and last words:
re.sub(r'^\s*(\w+).*?(\w+)$', r'\1 \2', a, flags=re.DOTALL)