validate.sh

Download
bash 267 lines 7.3 KB
  1#!/usr/bin/env bash
  2set -euo pipefail
  3
  4# Input Validation Using Bash Regex
  5# Demonstrates various validation patterns using bash's =~ operator and BASH_REMATCH
  6
  7# ============================================================================
  8# Color definitions for output
  9# ============================================================================
 10
 11readonly RED='\033[0;31m'
 12readonly GREEN='\033[0;32m'
 13readonly YELLOW='\033[1;33m'
 14readonly BLUE='\033[0;34m'
 15readonly NC='\033[0m' # No Color
 16
 17# ============================================================================
 18# Validation Functions
 19# ============================================================================
 20
 21# Validate email address format
 22validate_email() {
 23    local email="$1"
 24
 25    # Email regex: local-part@domain.tld
 26    # Simplified pattern for demonstration
 27    local email_regex='^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
 28
 29    if [[ "$email" =~ $email_regex ]]; then
 30        # BASH_REMATCH[0] contains the entire match
 31        echo -e "${GREEN}${NC} Valid email: $email"
 32        return 0
 33    else
 34        echo -e "${RED}${NC} Invalid email: $email"
 35        return 1
 36    fi
 37}
 38
 39# Validate IPv4 address
 40validate_ipv4() {
 41    local ip="$1"
 42
 43    # IPv4 regex with capturing groups for each octet
 44    local ip_regex='^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$'
 45
 46    if [[ ! "$ip" =~ $ip_regex ]]; then
 47        echo -e "${RED}${NC} Invalid IPv4 format: $ip"
 48        return 1
 49    fi
 50
 51    # Check each octet is in valid range (0-255)
 52    # BASH_REMATCH[1-4] contain the four octets
 53    local octet
 54    for i in 1 2 3 4; do
 55        octet="${BASH_REMATCH[$i]}"
 56        if [[ $octet -gt 255 ]]; then
 57            echo -e "${RED}${NC} Invalid IPv4 (octet $octet > 255): $ip"
 58            return 1
 59        fi
 60    done
 61
 62    echo -e "${GREEN}${NC} Valid IPv4: $ip (octets: ${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.${BASH_REMATCH[3]}.${BASH_REMATCH[4]})"
 63    return 0
 64}
 65
 66# Validate date in YYYY-MM-DD format with range checks
 67validate_date() {
 68    local date_str="$1"
 69
 70    # Date regex with capturing groups for year, month, day
 71    local date_regex='^([0-9]{4})-([0-9]{2})-([0-9]{2})$'
 72
 73    if [[ ! "$date_str" =~ $date_regex ]]; then
 74        echo -e "${RED}${NC} Invalid date format: $date_str (expected YYYY-MM-DD)"
 75        return 1
 76    fi
 77
 78    local year="${BASH_REMATCH[1]}"
 79    local month="${BASH_REMATCH[2]}"
 80    local day="${BASH_REMATCH[3]}"
 81
 82    # Basic range validation
 83    if [[ $month -lt 1 || $month -gt 12 ]]; then
 84        echo -e "${RED}${NC} Invalid month: $month (must be 01-12)"
 85        return 1
 86    fi
 87
 88    if [[ $day -lt 1 || $day -gt 31 ]]; then
 89        echo -e "${RED}${NC} Invalid day: $day (must be 01-31)"
 90        return 1
 91    fi
 92
 93    if [[ $year -lt 1900 || $year -gt 2100 ]]; then
 94        echo -e "${YELLOW}${NC} Date year out of typical range: $year"
 95    fi
 96
 97    echo -e "${GREEN}${NC} Valid date: $date_str (Y=$year, M=$month, D=$day)"
 98    return 0
 99}
100
101# Validate semantic version (e.g., 1.2.3, 2.0.0-beta, 1.0.0+build123)
102validate_semver() {
103    local version="$1"
104
105    # Semantic versioning regex: major.minor.patch[-prerelease][+buildmetadata]
106    local semver_regex='^([0-9]+)\.([0-9]+)\.([0-9]+)(-([a-zA-Z0-9.-]+))?(\+([a-zA-Z0-9.-]+))?$'
107
108    if [[ ! "$version" =~ $semver_regex ]]; then
109        echo -e "${RED}${NC} Invalid semver: $version"
110        return 1
111    fi
112
113    local major="${BASH_REMATCH[1]}"
114    local minor="${BASH_REMATCH[2]}"
115    local patch="${BASH_REMATCH[3]}"
116    local prerelease="${BASH_REMATCH[5]}"
117    local build="${BASH_REMATCH[7]}"
118
119    echo -e "${GREEN}${NC} Valid semver: $version"
120    echo "    Major: $major, Minor: $minor, Patch: $patch"
121    [[ -n "$prerelease" ]] && echo "    Prerelease: $prerelease"
122    [[ -n "$build" ]] && echo "    Build: $build"
123
124    return 0
125}
126
127# Validate URL (http/https)
128validate_url() {
129    local url="$1"
130
131    # URL regex with protocol, host, optional port, optional path
132    local url_regex='^(https?)://([a-zA-Z0-9.-]+)(:[0-9]+)?(/[^[:space:]]*)?$'
133
134    if [[ ! "$url" =~ $url_regex ]]; then
135        echo -e "${RED}${NC} Invalid URL: $url"
136        return 1
137    fi
138
139    local protocol="${BASH_REMATCH[1]}"
140    local host="${BASH_REMATCH[2]}"
141    local port="${BASH_REMATCH[3]}"
142    local path="${BASH_REMATCH[4]}"
143
144    echo -e "${GREEN}${NC} Valid URL: $url"
145    echo "    Protocol: $protocol"
146    echo "    Host: $host"
147    [[ -n "$port" ]] && echo "    Port: ${port:1}"  # Remove leading colon
148    [[ -n "$path" ]] && echo "    Path: $path"
149
150    return 0
151}
152
153# ============================================================================
154# Demo Section
155# ============================================================================
156
157demo_email_validation() {
158    echo -e "\n${BLUE}=== Email Validation ===${NC}\n"
159
160    local -a test_emails=(
161        "user@example.com"
162        "john.doe+tag@company.co.uk"
163        "invalid@"
164        "@example.com"
165        "no-at-sign.com"
166        "test@domain"
167        "valid.email@subdomain.example.com"
168    )
169
170    for email in "${test_emails[@]}"; do
171        validate_email "$email"
172    done
173}
174
175demo_ipv4_validation() {
176    echo -e "\n${BLUE}=== IPv4 Validation ===${NC}\n"
177
178    local -a test_ips=(
179        "192.168.1.1"
180        "10.0.0.1"
181        "255.255.255.255"
182        "256.1.1.1"
183        "192.168.1"
184        "192.168.1.1.1"
185        "0.0.0.0"
186    )
187
188    for ip in "${test_ips[@]}"; do
189        validate_ipv4 "$ip"
190    done
191}
192
193demo_date_validation() {
194    echo -e "\n${BLUE}=== Date Validation ===${NC}\n"
195
196    local -a test_dates=(
197        "2024-01-15"
198        "2024-12-31"
199        "2024-13-01"
200        "2024-01-32"
201        "24-01-15"
202        "2024/01/15"
203        "1850-06-15"
204    )
205
206    for date in "${test_dates[@]}"; do
207        validate_date "$date"
208    done
209}
210
211demo_semver_validation() {
212    echo -e "\n${BLUE}=== Semantic Version Validation ===${NC}\n"
213
214    local -a test_versions=(
215        "1.0.0"
216        "2.5.13"
217        "1.0.0-alpha"
218        "1.0.0-beta.1"
219        "1.0.0+20240115"
220        "1.0.0-rc.1+build.456"
221        "v1.0.0"
222        "1.0"
223    )
224
225    for version in "${test_versions[@]}"; do
226        validate_semver "$version"
227    done
228}
229
230demo_url_validation() {
231    echo -e "\n${BLUE}=== URL Validation ===${NC}\n"
232
233    local -a test_urls=(
234        "https://example.com"
235        "http://localhost:8080"
236        "https://api.example.com/v1/users"
237        "https://sub.domain.example.com:443/path?query=1"
238        "ftp://example.com"
239        "example.com"
240        "http://"
241    )
242
243    for url in "${test_urls[@]}"; do
244        validate_url "$url"
245    done
246}
247
248# ============================================================================
249# Main Execution
250# ============================================================================
251
252main() {
253    echo -e "${BLUE}╔════════════════════════════════════════════╗${NC}"
254    echo -e "${BLUE}║  Input Validation with Bash Regex Demo    ║${NC}"
255    echo -e "${BLUE}╚════════════════════════════════════════════╝${NC}"
256
257    demo_email_validation
258    demo_ipv4_validation
259    demo_date_validation
260    demo_semver_validation
261    demo_url_validation
262
263    echo -e "\n${GREEN}=== All Validation Demos Complete ===${NC}\n"
264}
265
266main "$@"