Variable Basics

Variables are fundamental building blocks in Bash scripting. They allow you to store data, make scripts flexible, and create reusable code. Understanding how to work with variables effectively is essential for writing robust shell scripts.

What are Variables?

Variables are named storage locations that hold data. In Bash, variables can store: - Text strings - Numbers (treated as strings) - Command output - File paths - Configuration values

Variable Declaration and Assignment

Basic Syntax

# Variable assignment (no spaces around =)
variable_name="value"

# Examples
name="John Doe"
age=25
city="New York"
is_active=true

Important Rules

  1. No spaces around the equals sign
  2. Case sensitive: name and Name are different variables
  3. No type declaration needed
  4. Quote values with spaces or special characters

Common Mistakes

# Wrong - spaces around =
name = "John"        # Error!

# Wrong - unquoted value with spaces
name=John Doe        # Error!

# Correct
name="John Doe"      # Correct

Variable Naming Conventions

Valid Variable Names

# Good variable names
username="john"
user_name="john"
userName="john"
USER_NAME="john"
file1="document.txt"
_private_var="secret"

Invalid Variable Names

# Invalid - cannot start with number
1name="john"         # Error!

# Invalid - contains special characters
user-name="john"     # Error!
user@name="john"     # Error!

# Invalid - reserved words
for="value"          # Error!
if="value"           # Error!

Best Practices

# Use descriptive names
config_file="/etc/myapp.conf"
max_connections=100
database_host="localhost"

# Use uppercase for constants
readonly PI=3.14159
readonly MAX_RETRIES=3

# Use lowercase for regular variables
current_user="john"
temp_directory="/tmp"

Accessing Variable Values

Basic Access

name="Alice"

# Access variable value
echo $name           # Alice
echo ${name}         # Alice (preferred for clarity)

When to Use Braces

name="Alice"

# Without braces - can be ambiguous
echo $names          # Empty (variable 'names' doesn't exist)

# With braces - clear separation
echo ${name}s        # Alices

# Concatenation examples
prefix="file"
echo ${prefix}_backup.txt    # file_backup.txt
echo $prefix_backup.txt      # Empty (looks for variable 'prefix_backup')

Variable Types and Behavior

String Variables

# Simple strings
greeting="Hello"
message="Welcome to Bash scripting"

# Strings with special characters
path="/home/user/My Documents"
command="ls -la"

# Empty strings
empty_var=""
another_empty=""

Numeric Variables

# Numbers are stored as strings but can be used in arithmetic
count=10
price=19.99
year=2024

# Arithmetic operations
total=$((count * 2))
echo $total          # 20

# Comparison
if [ $count -gt 5 ]; then
    echo "Count is greater than 5"
fi

Boolean-like Variables

# Bash doesn't have true boolean types
# Use strings to represent boolean values
is_enabled="true"
debug_mode="false"
has_permission="yes"

# Check boolean-like values
if [ "$is_enabled" = "true" ]; then
    echo "Feature is enabled"
fi

Variable Scope

Global Variables

#!/bin/bash
# Global variable - accessible everywhere
global_var="I'm global"

function test_function() {
    echo "Inside function: $global_var"
}

echo "Outside function: $global_var"
test_function

Local Variables

#!/bin/bash
function test_local() {
    local local_var="I'm local"
    global_var="Modified global"

    echo "Local variable: $local_var"
    echo "Global variable: $global_var"
}

global_var="Original global"
echo "Before function: $global_var"

test_local

echo "After function: $global_var"
echo "Local variable outside: $local_var"  # Empty

Reading User Input

Basic Input

#!/bin/bash
echo "What's your name?"
read name
echo "Hello, $name!"

Input with Prompt

#!/bin/bash
read -p "Enter your age: " age
echo "You are $age years old"

Multiple Variables

#!/bin/bash
echo "Enter first and last name:"
read first_name last_name
echo "Hello, $first_name $last_name!"

Reading into Array

#!/bin/bash
echo "Enter three colors:"
read -a colors
echo "First color: ${colors[0]}"
echo "All colors: ${colors[@]}"

Silent Input (Passwords)

#!/bin/bash
read -s -p "Enter password: " password
echo  # New line after hidden input
echo "Password length: ${#password}"

Variable Assignment Methods

Direct Assignment

name="John"
age=25

Command Substitution

# Modern syntax (preferred)
current_date=$(date)
file_count=$(ls | wc -l)
current_user=$(whoami)

# Legacy syntax (still works)
current_date=`date`
file_count=`ls | wc -l`

Reading from Files

# Read first line of file
first_line=$(head -n1 /etc/passwd)

# Read entire file content
file_content=$(cat /etc/hostname)

# Read with error handling
if config=$(cat config.txt 2>/dev/null); then
    echo "Config loaded: $config"
else
    echo "Failed to read config file"
fi

Arithmetic Assignment

# Simple arithmetic
count=5
count=$((count + 1))
echo $count          # 6

# Using let command
let count=count+1
echo $count          # 7

# Increment/decrement
((count++))
echo $count          # 8

Variable Manipulation

String Length

text="Hello World"
echo ${#text}        # 11

Substring Extraction

text="Hello World"

# Extract substring: ${variable:start:length}
echo ${text:0:5}     # Hello
echo ${text:6}       # World
echo ${text:6:3}     # Wor
echo ${text: -5}     # World (note the space before -)

Case Conversion

text="Hello World"

# Convert to uppercase (Bash 4+)
echo ${text^^}       # HELLO WORLD

# Convert to lowercase (Bash 4+)
echo ${text,,}       # hello world

# Convert first character
echo ${text^}        # Hello World
echo ${text,}        # hello World

Pattern Replacement

filename="document.txt"

# Replace first occurrence
echo ${filename/txt/pdf}     # document.pdf

# Replace all occurrences
echo ${filename//t/T}        # documenT.TxT

# Remove from beginning
echo ${filename#doc}         # ument.txt

# Remove from end
echo ${filename%.txt}        # document

Default Values and Error Handling

Default Values

# Use default if variable is unset or empty
name=${name:-"Anonymous"}
echo "Hello, $name"

# Set default if variable is unset
name=${name:="Default Name"}

# Use alternative if variable is set
message=${name:+"Hello, $name"}

Error on Unset Variables

# Exit with error if variable is unset
required_var=${required_var:?"Variable required_var must be set"}

# Custom error message
database_host=${database_host:?"Error: DATABASE_HOST environment variable is required"}

Practical Example

#!/bin/bash
# Configuration script with defaults

# Set defaults
config_file=${CONFIG_FILE:-"/etc/myapp.conf"}
log_level=${LOG_LEVEL:-"INFO"}
max_connections=${MAX_CONNECTIONS:-"100"}

echo "Configuration:"
echo "Config file: $config_file"
echo "Log level: $log_level"
echo "Max connections: $max_connections"

# Validate required variables
database_url=${DATABASE_URL:?"Error: DATABASE_URL must be set"}
api_key=${API_KEY:?"Error: API_KEY must be set"}

Variable Arrays (Preview)

Simple Array

# Create array
fruits=("apple" "banana" "orange")

# Access elements
echo ${fruits[0]}    # apple
echo ${fruits[1]}    # banana

# All elements
echo ${fruits[@]}    # apple banana orange

# Array length
echo ${#fruits[@]}   # 3

Best Practices

1. Always Quote Variables

# Good - prevents word splitting
if [ "$name" = "John Doe" ]; then
    echo "Hello, $name"
fi

# Bad - can break with spaces
if [ $name = "John Doe" ]; then
    echo "Hello, $name"
fi

2. Use Meaningful Names

# Good
database_connection_string="mysql://localhost:3306/mydb"
max_retry_attempts=3

# Bad
dcs="mysql://localhost:3306/mydb"
mra=3

3. Initialize Variables

# Good - initialize variables
count=0
total=0
error_message=""

# Process data
for file in *.txt; do
    ((count++))
    # ... processing ...
done

4. Use readonly for Constants

# Constants should be readonly
readonly PI=3.14159
readonly MAX_USERS=1000
readonly CONFIG_DIR="/etc/myapp"

# This will cause an error
# PI=3.14  # Error: PI is readonly

5. Validate Input

#!/bin/bash
read -p "Enter a number: " number

# Validate input
if [[ ! $number =~ ^[0-9]+$ ]]; then
    echo "Error: Please enter a valid number"
    exit 1
fi

echo "You entered: $number"

Common Variable Patterns

Configuration Variables

#!/bin/bash
# Application configuration

# Default configuration
APP_NAME="MyApplication"
APP_VERSION="1.0.0"
CONFIG_FILE="/etc/${APP_NAME,,}.conf"
LOG_FILE="/var/log/${APP_NAME,,}.log"
PID_FILE="/var/run/${APP_NAME,,}.pid"

# Load configuration file if it exists
if [ -f "$CONFIG_FILE" ]; then
    source "$CONFIG_FILE"
fi

Temporary Variables

#!/bin/bash
# Temporary file handling

temp_dir=$(mktemp -d)
temp_file=$(mktemp)

# Cleanup function
cleanup() {
    rm -rf "$temp_dir"
    rm -f "$temp_file"
}

# Set trap to cleanup on exit
trap cleanup EXIT

# Use temporary files
echo "Processing data..." > "$temp_file"

Understanding variable basics is crucial for Bash scripting. Variables make your scripts flexible, maintainable, and powerful. Practice these concepts and patterns to build a solid foundation for more advanced scripting techniques.