Data processing often involves cleaning unstructured text to extract meaningful numerical data. Whether you are parsing logs, user input, or messy data files, Regular Expressions (Regex) are the most efficient tool for this job.
This guide explains how to extract integers and floating-point numbers from a string, calculate their average, and format the output using Python.
Understanding the Regex Pattern
To extract numbers mixed with text (e.g., "Item: 5 cost: 12.99"), simple string splitting won't work because delimiters vary. We need a regex pattern that can match:
- Integers (e.g.,
10,5) - Floats (e.g.,
3.14,0.5) - Negative numbers (e.g.,
-5)
The pattern r"[-+]?\d*\.\d+|\d+" covers these cases:
[-+]?: Optional+or-sign.\d*\.\d+: Matches floats (digits before dot, dot, digits after dot).|: OR operator.\d+: Matches integers (one or more digits).
Step 1: Extracting Numbers
We use re.findall() to retrieve all non-overlapping matches as a list of strings.
import re
text = "Temperature is -5.5, pressure is 1013, and humidity 40%."
pattern = r"[-+]?\d*\.\d+|\d+"
matches = re.findall(pattern, text)
print(f"Extracted strings: {matches}")Output:
Extracted strings: ['-5.5', '1013', '40']Step 2: Calculating and Formatting
Once extracted, the data exists as strings. We must convert them to float, calculate the average, and then format the result to 2 decimal places.
matches = ['-5.5', '1013', '40']
numbers = [float(n) for n in matches]
if len(numbers) > 0:
average = sum(numbers) / len(numbers)
else:
average = 0
formatted_avg = f"{average:.2f}"
print(f"Average: {formatted_avg}")Output:
Average: 349.17Step 3: Handling Command Line Arguments
To make the script reusable from the terminal, we use the sys module to read arguments passed during execution (e.g., python script.py "some text").
sys.argv[0]: The name of the script.sys.argv[1]: The first argument passed by the user.
Complete Code Solution
Here is the complete find_num.py script combining regex extraction, math, and CLI argument handling.
import re
import sys
def calculate_average(text):
"""
Extracts numbers from text and returns their average
formatted to 2 decimal places.
"""
numbers = re.findall(r"[-+]?\d*\.\d+|\d+", text)
if not numbers:
return "0.00"
numbers = [float(num) for num in numbers]
average = sum(numbers) / len(numbers)
return "{:.2f}".format(average)
if __name__ == "__main__":
if len(sys.argv) > 1:
input_text = sys.argv[1]
result = calculate_average(input_text)
print(result)
else:
print("Error: Please provide a string argument.")Testing the Script
Test Case 1
python3 find_num.py "a11 b3.14c15 16"Output:
11.29Test Case 2
python3 find_num.py "a 5 b 6 c7 dd8 9"Output:
7.00Conclusion
By combining re.findall with basic list comprehensions, you can extract numerical data from chaotic text strings efficiently.
- Regex:
r"[-+]?\d*\.\d+|\d+"captures mostly any number format. - Conversion: Always convert regex matches (strings) to
floatorintbefore math. - Formatting: Use
"{:.2f}".format()to ensure clean, readable output.