The elegant way to replace specific characters in Python - python

I have strings that are unpredictable in terms of character content, but I know that every string contains exactly one character '*'.
How to replace two characters after the '*' with some non hard-coded string. Non hard-coded string is actually calculated checksum and converted into string:
checksum_str = str(hex(csum).lstrip('0x'))

You want something like:
star_pos = my_string.find('*')
my_string = my_string[:star_pos] + '*' + checksum_str + my_string[star_pos + 3:]

You can do it with a regular expression:
import re
my_string = re.sub(r'(?<=\*)..', checksum_str, my_string, 1)

Related

How to get value of "string"?

Given strings like:
"hello"
'hello'
I want to remove only first and last char if:
They are the same
They are " or '
I.e., given 'hello' I'm expecting hello. Given 'hello" I'm not expecting it to change.
I was able to do this by reading first char and last char, validating they are the same + validating they are equal to ' or " and validating it's not the the same index for char (because I don't want this: ' to end up as the empty string). With all edge cases checking I ended with 10s of lines.
What's your approach to solve this?
In simple words, Given a string in Python format I want to return its data and if it's not valid to keep it as is.
Sounds like a job for regular expressions with groups:
import re
re.sub(r'^([\'"])(.*)(\1)$', r'\2', s)
Which reads as:
^ - match the beginning of the string
(['"]) - either single or double quote (group 1)
(.*) any (possibly, empty) sequence of characters in between (group 2)
(\1) - the same character as in group 1
$ - end of the string
If the string matches the pattern above, replace it with the content of the group 2.
For example:
>>> s = re.sub(r'^([\'"])(.*)(\1)$', r'\2', "'hello'")
>>> print(s)
hello
An alternative way could be with ast.literal_eval(), but it won't handle non-matching quotes.
I would use str.endswith and str.startswith, although it still gets a bit long:
def readstring(string):
if len(string)>1 and (string.startswith('"') and string.endswith('"') or string.startswith("'") and string.endswith("'")):
return string[1:-1]
return string

Python - Split string on first occurrence of non-allowable characters

I have some python code where i want to scan and split string on first occurrence of non-allowable characters.
import re,string
mystring="my_id=abc-something_123&anything#;?lcdkahck;my_id%3Dkckdkkj_bcjc"
if "my_id=" in mystring:
mystring = mystring[mystring.index("my_id=") + 6 : len(mystring)][0:100]
mystring = re.split('[;&#]', mystring)[0]
print(mystring)
What happens in this, I get string correctly where ;&# is coming, but my data can have any unpredictable character put of ;&#.
What i tried drive out these characters
allowable_character = '-' + '_' + string.ascii_letters + string.digits
mystring = re.sub('[^%s]' % allowable_character, '', mystring)
print(mystring)
But this just filters the string with characters that are not in 'allowable_character'.
What i am trying to achieve is to split string once the character which is not in 'allowable_character' and return that string.
So I want expected output as 'abc-something_123'
Any help is appreciated here
You could just use re.findall here:
mystring = "my_id=abc-something_123&anything#;?lcdkahck;my_id%3Dkckdkkj_bcjc"
match = re.findall(r'^my_id=([\w-]*).*$', mystring)[0]
print(match)
This prints:
'abc-something_123'

regex replace '...' at the end of the string

I have a string like:
text1 = 'python...is...fun...'
I want to replace the multiple '.'s to one '.' only when they are at the end of the string, i want the output to be:
python...is...fun.
So when there is only one '.' at the end of the string, then it won't be replaced
text2 = 'python...is...fun.'
and the output is just the same as text2
My regex is like this:
text = re.sub(r'(.*)\.{2,}$', r'\1.', text)
which i want to match any string then {2 to n} of '.' at the end of the string, but the output is:
python...is...fun..
any ideas how to do this?
Thx in advance!
You are making it a bit complex, you can easily do it by using regex as \.+$ and replace the regex pattern with single . character.
>>> text1 = 'python...is...fun...'
>>> new_text = re.sub(r"\.+$", ".", text1)
>>> 'python...is...fun.'
You may extend this regex further to handle the cases with input such as ... only, etc but the main concept was that there is no need to counting the number of ., as you have done in your answer.
Just look for the string ending with three periods, and replace them with a single one.
import re
x = "foo...bar...quux..."
print(re.sub('\.{2,}$', '.', x))
// foo...bar...quux.
import re
print(re.sub(r'\.{2,}$', '.', 'I...love...python...'))
As simple as that. Note that you need to escape the . because otherwise, it means whichever char
except \n.
I want to replace the multiple '.'s to one '.' only when they are at
the end of the string
For such simple case it's easier to substitute without importing re module, checking the value of the last 3 characters:
text1 = 'python...is...fun...'
text1 = text1[:-2] if text1[-3:] == '...' else text1
print(text1)
The output:
python...is...fun.

Splitting a string using re module of python

I have a string
s = 'count_EVENT_GENRE in [1,2,3,4,5]'
#I have to capture only the field 'count_EVENT_GENRE'
field = re.split(r'[(==)(>=)(<=)(in)(like)]', s)[0].strip()
#o/p is 'cou'
# for s = 'sum_EVENT_GENRE in [1,2,3,4,5]' o/p = 'sum_EVENT_GENRE'
which is fine
My doubt is for any character in (in)(like) it is splitting the string s at that character and giving me first slice.(as after "cou" it finds one matching char i:e n). It's happening for any string that contains any character from (in)(like).
Ex : 'percentage_AMOUNT' o/p = 'p'
as it finds a matching char as 'e' after p.
So i want some advice how to treat (in)(like) as words not as characters , when splitting occurs/matters.
please suggest a syntax.
Answering your question, the [(==)(>=)(<=)(in)(like)] is a character class matching single characters you defined inside the class. To match sequences of characters, you need to remove [ and ] and use alternation:
r'==?|>=?|<=?|\b(?:in|like)\b'
or better:
r'[=><]=?|\b(?:in|like)\b'
You code would look like:
import re
ss = ['count_EVENT_GENRE in [1,2,3,4,5]','coint_EVENT_GENRE = "ROMANCE"']
for s in ss:
field = re.split(r'[=><]=?|\b(?:in|like)\b', s)[0].strip()
print(field)
However, there might be other (easier, or safer - depending on the actual specifications) ways to get what you want (splitting with space and getting the first item, use re.match with r'\w+' or r'[a-z]+(?:_[A-Z]+)+', etc.)
If your value is at the start of the string and starts with lowercase ASCII letters, and then can have any amount of sequences of _ followed with uppercase ASCII letters, use:
re.match(r'[a-z]+(?:_[A-Z]+)*', s)
Full demo code:
import re
ss = ['count_EVENT_GENRE in [1,2,3,4,5]','coint_EVENT_GENRE = "ROMANCE"']
for s in ss:
fieldObj = re.match(r'[a-z]+(?:_[A-Z]+)*', s)
if fieldObj:
print(fieldObj.group())
If you want only the first word of your string, then this should do the job:
import re
s = 'count_EVENT_GENRE in [1,2,3,4,5]'
field = re.split(r'\W', s)[0]
# count_EVENT_GENRE
Is there anything wrong with using split?
>>> s = 'count_EVENT_GENRE in [1,2,3,4,5]'
>>> s.split(' ')[0]
'count_EVENT_GENRE'
>>> s = 'coint_EVENT_GENRE = "ROMANCE"'
>>> s.split(' ')[0]
'coint_EVENT_GENRE'
>>>

Breaking up substrings in Python based on characters

I am trying to write code that will take a string and remove specific data from it. I know that the data will look like the line below, and I only need the data within the " " marks, not the marks themselves.
inputString = 'type="NN" span="123..145" confidence="1.0" '
Is there a way to take a Substring of a string within two characters to know the start and stop points?
You can extract all the text between pairs of " characters using regular expressions:
import re
inputString='type="NN" span="123..145" confidence="1.0" '
pat=re.compile('"([^"]*)"')
while True:
mat=pat.search(inputString)
if mat is None:
break
strings.append(mat.group(1))
inputString=inputString[mat.end():]
print strings
or, easier:
import re
inputString='type="NN" span="123..145" confidence="1.0" '
strings=re.findall('"([^"]*)"', inputString)
print strings
Output for both versions:
['NN', '123..145', '1.0']
fields = inputString.split('"')
print fields[1], fields[3], fields[5]
You could split the string at each space to get a list of 'key="value"' substrings and then use regular expressions to parse the substrings.
Using your input string:
>>> input_string = 'type="NN" span="123..145" confidence="1.0" '
>>> input_string_split = input_string.split()
>>> print input_string_split
[ 'type="NN"', 'span="123..145"', 'confidence="1.0"' ]
Then use regular expressions:
>>> import re
>>> pattern = r'"([^"]+)"'
>>> for substring in input_string_split:
match_obj = search(pattern, substring)
print match_obj.group(1)
NN
123..145
1.0
The regular expression '"([^"]+)"' matches anything within quotation marks (provided there is at least one character). The round brackets indicate the bit of the regular expression that you are interested in.

Categories