How to extract with a regex the 3 numerical values of coordinates of this string, whether they are positive or negative numerical coordinates
Question:
import asyncio
import re
import time
from datetime import datetime
detection_timer = 0
detection_timer_increment = 5
detection_timer_change = 10
x, y , z = None, None, None
x_aux, y_aux, z_aux = 0, 0, 0
def get_coords(input_coords):
input_coords = input_coords.replace("@","0") #convierte todos los posibles caracteres @ en caracteres 0
m = re.match(r".*:s*([0-9.]*?)s*,s*([0-9.]*?)s*,s*([0-9.]*?)$", input_coords) #No agarra los numeros negativos
if m:
return m.groups()
async def timer():
global x, y, z, x_aux, y_aux, z_aux
global input_coords
global detection_timer, detection_timer_change
detection_timer += detection_timer_increment
#Debe entrar a este if cara cierto tiempo
if(detection_timer >= detection_timer_change):
detection_timer = 0 #resetea contador
#detect_color()
r = get_coords(input_coords)
if r:
x_aux = x = float(r[0]) if r[0] else x
y_aux = y = float(r[1]) if r[1] else y
z_aux = z = float(r[2]) if r[2] else z
return x_aux, y_aux, z_aux
while True:
#Some examples of possible inputs
#input_coords = "Coordenadas: @, 63, -5|hhhf♀"
#input_coords = "Coordenadas: @, 63.5, -5.695|hhhf♀"
#input_coords = "Coordenadas: @, hhkjkm♀-63ss, -5|hhhf♀"
#input_coords = "Coordenadas: -8, 63, -5 n♀"
input_coords = "Coordenadas: @, 63, -5"
x_aux, y_aux, z_aux = asyncio.run(timer())
if(x_aux != None and y_aux != None and z_aux != None):
print(x_aux)
print(y_aux)
print(z_aux)
Although the code does not work well, in case they are negative coordinates or if there are more values at the end of the string.
How should I correct this regex so that it can capture the example values that I put in the code?
"Coordenadas: @, 63, -5|hhhf♀" —-> this should extract 0,63,-5
"Coordenadas: @, 63.5, -5.695|hhhf♀" —-> this should extract 0,63.5,-5.695
"Coordenadas: @, hhkjkm♀-63ss, -5|hhhf♀" —-> this should extract 0, -63, -5
"Coordenadas: -8, 63, -5 n♀" —-> this should extract -8,63,-5
"Coordenadas: @, 63, -5" —-> this should extract 0,63,-5
Answers:
Looks like you could simplify this greatly by just finding the numbers and padding with zeros on the left if you have less than 3 values:
s = "Coordenadas: @, hhkjkm♀-63ss, -5|hhhf♀"
import re
l = re.findall('-?d+', s)
out = [0]*(3-len(l))+list(map(int, l)
Output: [0, -63, -5]
NB. if you expect decimal values, use '-?d+(?:.d*)?'
and float
If you want to capture all 3 values in 3 capture groups (where your code replaces the @
to 0) you can:
- omit the anchor
$
to assert the end of the string
- match an optional
-
- note that not in all examples there is a number right after the comma like in
hhkjkm♀-63ss, -5|hhhf♀
The pattern might look like:
^[^:]*:s*(-?d+(?:.d+)?),D*?(-?d+(?:.d+)?)D*?(-?d+(?:.d+)?)
import re
def get_coords(input_coords):
input_coords = input_coords.replace("@", "0")
m = re.match(r"^[^:]*:s*(-?d+(?:.d+)?),D*?(-?d+(?:.d+)?)D*?(-?d+(?:.d+)?)", input_coords)
if m:
return m.groups()
strings = [
"Coordenadas: @, 63, -5|hhhf♀",
"Coordenadas: @, 63.5, -5.695|hhhf♀",
"Coordenadas: @, hhkjkm♀-63ss, -5|hhhf♀",
"Coordenadas: -8, 63, -5 n♀",
"Coordenadas: @, 63, -5"
]
for s in strings:
print(get_coords(s))
Output
('0', '63', '-5')
('0', '63.5', '-5.695')
('0', '-63', '-5')
('-8', '63', '-5')
('0', '63', '-5')
With your shown samples, taking inspiration from Thefourthbird’s answer; please try following regex too.
^".*?:s*(-?d+(?:.d+)?),D*?(-?d+(?:.d+)?).*?(-?d+(?:.d+)?)
Explanation: Adding detailed explanation for above.
^".*?:s* ##Matching from starting of value " followed by lazy match to match till 1st occurrence of : followed by 0 or more occurrences of spaces.
(-?d+(?:.d+)?) ##Creating 1st capturing group which has optional - as a match followed by 1 or more digits followed by optional .digits(to catch floating numbers).
,D*? ##Matching non-digits 0 or more occurrences of it.
(-?d+(?:.d+)?) ##Creating 2nd capturing group which has - as optional match followed by by 1 or more digits followed by optional .digits(to catch floating numbers).
.*? ##Mentioning lazy match here.
(-?d+(?:.d+)?) ##Creating 3rd capturing group which matches optional - here, 1 or more digits followed by optional .digits(to catch floating numbers).
import asyncio
import re
import time
from datetime import datetime
detection_timer = 0
detection_timer_increment = 5
detection_timer_change = 10
x, y , z = None, None, None
x_aux, y_aux, z_aux = 0, 0, 0
def get_coords(input_coords):
input_coords = input_coords.replace("@","0") #convierte todos los posibles caracteres @ en caracteres 0
m = re.match(r".*:s*([0-9.]*?)s*,s*([0-9.]*?)s*,s*([0-9.]*?)$", input_coords) #No agarra los numeros negativos
if m:
return m.groups()
async def timer():
global x, y, z, x_aux, y_aux, z_aux
global input_coords
global detection_timer, detection_timer_change
detection_timer += detection_timer_increment
#Debe entrar a este if cara cierto tiempo
if(detection_timer >= detection_timer_change):
detection_timer = 0 #resetea contador
#detect_color()
r = get_coords(input_coords)
if r:
x_aux = x = float(r[0]) if r[0] else x
y_aux = y = float(r[1]) if r[1] else y
z_aux = z = float(r[2]) if r[2] else z
return x_aux, y_aux, z_aux
while True:
#Some examples of possible inputs
#input_coords = "Coordenadas: @, 63, -5|hhhf♀"
#input_coords = "Coordenadas: @, 63.5, -5.695|hhhf♀"
#input_coords = "Coordenadas: @, hhkjkm♀-63ss, -5|hhhf♀"
#input_coords = "Coordenadas: -8, 63, -5 n♀"
input_coords = "Coordenadas: @, 63, -5"
x_aux, y_aux, z_aux = asyncio.run(timer())
if(x_aux != None and y_aux != None and z_aux != None):
print(x_aux)
print(y_aux)
print(z_aux)
Although the code does not work well, in case they are negative coordinates or if there are more values at the end of the string.
How should I correct this regex so that it can capture the example values that I put in the code?
"Coordenadas: @, 63, -5|hhhf♀" —-> this should extract 0,63,-5
"Coordenadas: @, 63.5, -5.695|hhhf♀" —-> this should extract 0,63.5,-5.695
"Coordenadas: @, hhkjkm♀-63ss, -5|hhhf♀" —-> this should extract 0, -63, -5
"Coordenadas: -8, 63, -5 n♀" —-> this should extract -8,63,-5
"Coordenadas: @, 63, -5" —-> this should extract 0,63,-5
Looks like you could simplify this greatly by just finding the numbers and padding with zeros on the left if you have less than 3 values:
s = "Coordenadas: @, hhkjkm♀-63ss, -5|hhhf♀"
import re
l = re.findall('-?d+', s)
out = [0]*(3-len(l))+list(map(int, l)
Output: [0, -63, -5]
NB. if you expect decimal values, use '-?d+(?:.d*)?'
and float
If you want to capture all 3 values in 3 capture groups (where your code replaces the @
to 0) you can:
- omit the anchor
$
to assert the end of the string - match an optional
-
- note that not in all examples there is a number right after the comma like in
hhkjkm♀-63ss, -5|hhhf♀
The pattern might look like:
^[^:]*:s*(-?d+(?:.d+)?),D*?(-?d+(?:.d+)?)D*?(-?d+(?:.d+)?)
import re
def get_coords(input_coords):
input_coords = input_coords.replace("@", "0")
m = re.match(r"^[^:]*:s*(-?d+(?:.d+)?),D*?(-?d+(?:.d+)?)D*?(-?d+(?:.d+)?)", input_coords)
if m:
return m.groups()
strings = [
"Coordenadas: @, 63, -5|hhhf♀",
"Coordenadas: @, 63.5, -5.695|hhhf♀",
"Coordenadas: @, hhkjkm♀-63ss, -5|hhhf♀",
"Coordenadas: -8, 63, -5 n♀",
"Coordenadas: @, 63, -5"
]
for s in strings:
print(get_coords(s))
Output
('0', '63', '-5')
('0', '63.5', '-5.695')
('0', '-63', '-5')
('-8', '63', '-5')
('0', '63', '-5')
With your shown samples, taking inspiration from Thefourthbird’s answer; please try following regex too.
^".*?:s*(-?d+(?:.d+)?),D*?(-?d+(?:.d+)?).*?(-?d+(?:.d+)?)
Explanation: Adding detailed explanation for above.
^".*?:s* ##Matching from starting of value " followed by lazy match to match till 1st occurrence of : followed by 0 or more occurrences of spaces.
(-?d+(?:.d+)?) ##Creating 1st capturing group which has optional - as a match followed by 1 or more digits followed by optional .digits(to catch floating numbers).
,D*? ##Matching non-digits 0 or more occurrences of it.
(-?d+(?:.d+)?) ##Creating 2nd capturing group which has - as optional match followed by by 1 or more digits followed by optional .digits(to catch floating numbers).
.*? ##Mentioning lazy match here.
(-?d+(?:.d+)?) ##Creating 3rd capturing group which matches optional - here, 1 or more digits followed by optional .digits(to catch floating numbers).