Find a string within a string using pattern matching in python

Clash Royale CLAN TAG#URR8PPP
Find a string within a string using pattern matching in python
I'd like to use part of a string ('project') that is returned from an API. The string looks like this:
'Project Title': 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'
I'd like to store the 'LS003942_EP... ' part in a new variable called foldername. I'm thought a good way would be to use a regex to find the text after Title. Here's my code:
foldername
Title
orders = api.get_all(view='Folder', fields='Project Title', maxRecords=1)
for new in orders:
print ("Found 1 new project")
print (new['fields'])
project = (new['fields'])
s = re.search('Title(.+?)', result)
if s:
foldername = s.group(1)
print(foldername)
This gives me an error -
TypeError: expected string or bytes-like object.
I'm hoping for foldername = 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'
foldername = 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'
json.parse
@MaximilianPeters Properly formatted JSON has double quotes around each string property and value. But yeah, probably good to replace the single-quotes with double-quotes and parse it like that
– CertainPerformance
Aug 6 at 8:19
@CertainPerformance: right, I always mix the two.
– Maximilian Peters
Aug 6 at 8:21
@MaximilianPeters @CertainPerformance: That also looks like a valid Python dict, so
ast.literal_eval() should work...– AKX
Aug 6 at 8:23
ast.literal_eval()
@AKX correct, even the builtin python function
eval should work just fine– Johny Vaknin
Aug 6 at 8:29
eval
3 Answers
3
You can use ast.literal_eval to safely evaluate a string containing a Python literal:
ast.literal_eval
import ast
s = "'Project Title': 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'"
print(ast.literal_eval(s)['Project Title'])
# LS003942_EP - 5 Random Road, Sunny Place, SA 5000
It seems (to me) that you have a dictionary and not string. Considering this case, you may try:
s = 'Project Title': 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'
print(s['Project Title'])
If you have time, take a look at dictionaries.
Thanks. This looks like a simple solution. I tried and got the following error. I'm not very sure why: raise ValueError('malformed node or string: ' + repr(node)) ValueError: malformed node or string: 'Project Title': 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'
– Neil
Aug 7 at 8:21
Can you try out my updated answer.
– Austin
Aug 7 at 10:25
Awesome! Thank worked. Thanks for taking the time to explain. I'll have a look at dictionaries!
– Neil
Aug 8 at 3:30
One thing, how can i ensure the output is in quotes? E.g. the output looks like: 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000' ?
– Neil
Aug 8 at 5:24
Okay, do
print(repr(s['Project Title'])).– Austin
Aug 8 at 5:31
print(repr(s['Project Title']))
I don't think you need a regex here:
regex
string = "'Project Title': 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'"
foldername = string[string.index(":") + 2: len(string)-1]
Essentially, I'm finding the position of the first colon, then adding 2 to get the starting index of your foldername (which would be the apostrophe), and then I use index slicing and slice everything from the index to the second-last character (the last apostrophe).
However, if your string is always going to be in the form of a valid python dict, you could simply do foldername = (eval(string).values)[0]. Here, I'm treating your string as a dict and am getting the first value from it, which is your desired foldername. But, as @AKX notes in the comments, eval() isn't safe as somebody could pass malicious code as a string. Unless you're sure that your input strings won't contain code (which is unlikely), it's best to use ast.literal_eval() as it only evaluates literals.
dict
foldername = (eval(string).values)[0]
dict
foldername
eval()
But, as @MaximilianPeters notes in the comments, your response looks like a valid JSON, so you could easily parse it using json.parse().
json.parse()
Thanks. I wasn't able to figure out json.parse(). I think perhaps the lack of double quotes is the issue. I also tried your earlier suggestion but received the error below: foldername = string[string.index(":") + 2: len(string)-1] AttributeError: 'dict' object has no attribute 'index'
– Neil
Aug 7 at 8:17
@Neil Is
'Project Title': 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000' stored as a dictionary?? Your wording implied that it was stored as a string...– Adi219
Aug 7 at 8:24
'Project Title': 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'
I'm not entirely sure as i'm pretty new. This is the full response from the API and then i take the 'fields' part and store that.
– Neil
Aug 7 at 8:40
['id': 'rec52yhRTMYcetmxJ', 'fields': 'Project Title': 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000', 'createdTime': '2018-08-03T06:29:09.000Z']
– Neil
Aug 7 at 8:41
You could try this pattern: (?<='Project Title': )[^}]+.
(?<='Project Title': )[^}]+
Explanation: it uses positive lookbehind to assure, that match will occure after 'Project Title':. Then it matches until } is encountered: [^}]+.
'Project Title':
}
[^}]+
Demo
Thanks. I'm trying to match the whole string e.g. 'LS003942_EP - 5 Random Road, Sunny Place, SA 5000'. This seems to match the first part correctly?
– Neil
Aug 7 at 8:14
@Neil Try updated answer.
– Michał Turczyn
Aug 7 at 8:24
Thanks. It looks like the regex is right! I didn't go with it in the end as i found the other answer simpler to implement. But thank you so much.
– Neil
Aug 8 at 3:34
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
The response looks like a JSON. Why not use
json.parse?– Maximilian Peters
Aug 6 at 8:19