Validating an IP address format in Bash is a great example of using regular expressions (regex) for more complex pattern matching.
Since a typical IPv4 address consists of four numbers (octets) separated by dots, where each number is between 0 and 255, we can construct a regex that checks for this pattern.
Here's how you can do it:
#!/bin/bash
# Function to validate an IPv4 address
validate_ipv4() {
local ip=$1
local stat=1
# Regex for a *single* octet (0-255)
# (?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])
# 25[0-5] -> 250-255
# 2[0-4][0-9] -> 200-249
# 1[0-9]{2} -> 100-199
# [1-9][0-9] -> 10-99
# [0-9] -> 0-9
local octet_regex="(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])"
# Full IPv4 regex: four octets separated by dots
local ipv4_regex="^$octet_regex\.$octet_regex\.$octet_regex\.$octet_regex$"
if [[ $ip =~ $ipv4_regex ]]; then
stat=0 # Return 0 for success
fi
return $stat
}
# --- Main script logic ---
# Check if an argument is provided
if [ -z "$1" ]; then
echo "Usage: $0 <IP_ADDRESS>"
exit 1
fi
IP_TO_CHECK="$1"
if validate_ipv4 "$IP_TO_CHECK"; then
echo "'$IP_TO_CHECK' is a valid IPv4 address."
exit 0
else
echo "'$IP_TO_CHECK' is NOT a valid IPv4 address."
exit 1
fi
Explanation:
-
validate_ipv4() { ... }Function:- It's good practice to encapsulate validation logic in a function for reusability and readability.
local ip=$1: Assigns the first argument passed to the function to a local variableip.local stat=1: Initializes a status variable to 1 (indicating failure by default).
-
octet_regexBreakdown:- This is the core of the validation. It defines the pattern for a single number between 0 and 255.
25[0-5]: Matches numbers from 250 to 255.2[0-4][0-9]: Matches numbers from 200 to 249.1[0-9]{2}: Matches numbers from 100 to 199.[1-9][0-9]: Matches numbers from 10 to 99.[0-9]: Matches numbers from 0 to 9.- The
|acts as an "OR" operator, so it matches if any of these sub-patterns are true. (and)create a grouping.
-
ipv4_regexConstruction:^$octet_regex\.$octet_regex\.$octet_regex\.$octet_regex$: This combines four instances of theoctet_regex, separated by literal dots (\.).^: Asserts the position at the start of the string.$: Asserts the position at the end of the string.- This ensures the entire string must match the IP pattern, not just a part of it.
-
if [[ $ip =~ $ipv4_regex ]]; then:- This is the Bash
[[ ... ]]conditional construct with the=~operator, which performs regular expression matching. - If the
$ipvariable matches the$ipv4_regexpattern, the condition is true.
- This is the Bash
-
Return Status:
stat=0is set if there's a match, meaning the function returns0(success) if the IP is valid.return $statsets the exit status of the function.
-
Main Script Logic:
- Checks if an argument was even provided (
[ -z "$1" ]). - Calls the
validate_ipv4function. - Checks the exit status of the function (
if validate_ipv4 ...) to determine if it was successful (0) or failed (1), and prints the appropriate message.
- Checks if an argument was even provided (
How to test it:
Save the script as validate_ip.sh and make it executable (chmod +x validate_ip.sh).
./validate_ip.sh 192.168.1.1 # Valid
./validate_ip.sh 0.0.0.0 # Valid
./validate_ip.sh 255.255.255.255 # Valid
./validate_ip.sh 10.0.0.256 # Invalid (octet too high)
./validate_ip.sh 192.168.1 # Invalid (too few octets)
./validate_ip.sh 192.168.1.1.1 # Invalid (too many octets)
./validate_ip.sh hello # Invalid
./validate_ip.sh 192.168.1. # Invalid (trailing dot)
./validate_ip.sh .168.1.1 # Invalid (leading dot)
This script provides a robust way to check for valid IPv4 addresses. For IPv6, the regex would be significantly more complex, but the same principles of pattern matching apply!