5月29日 01:20
What are the common loop structures in Shell scripts? How to use for, while, and until loops?
Common loop structures in Shell scripts include for loops, while loops, and until loops.
for Loop
Basic Syntax
bashfor variable in list do commands done
Iterating Over Lists
bash# Iterate over string list for fruit in apple banana orange do echo "Fruit: $fruit" done # Iterate over number sequence for i in 1 2 3 4 5 do echo "Number: $i" done # Use seq command to generate sequence for i in $(seq 1 10) do echo "Number: $i" done # Use {start..end} syntax (Bash 3.0+) for i in {1..10} do echo "Number: $i" done # Specify step for i in {0..10..2} do echo "Number: $i" done
C-style for Loop
bash# C-style syntax for (( i=0; i<10; i++ )) do echo "Number: $i" done # Multiple variables for (( i=0, j=10; i<10; i++, j-- )) do echo "i=$i, j=$j" done
Iterating Over Files and Directories
bash# Iterate over files in current directory for file in *.txt do echo "Processing: $file" done # Iterate over command output for user in $(cut -d: -f1 /etc/passwd) do echo "User: $user" done # Recursively iterate over directories for file in $(find . -name "*.sh") do echo "Shell script: $file" done
while Loop
Basic Syntax
bashwhile condition do commands done
while Loop Examples
bash# Counter count=0 while [ $count -lt 5 ] do echo "Count: $count" count=$((count + 1)) done # Read file lines while IFS= read -r line do echo "Line: $line" done < input.txt # Read user input while true do read -p "Enter 'quit' to exit: " input if [ "$input" = "quit" ]; then break fi echo "You entered: $input" done # Wait for process to finish while ps -p $PID > /dev/null do echo "Process is running..." sleep 1 done echo "Process finished"
until Loop
Basic Syntax
bashuntil condition do commands done
until Loop Examples
bash# Wait for condition to be true count=0 until [ $count -ge 5 ] do echo "Count: $count" count=$((count + 1)) done # Wait for service to start until curl -s http://localhost:8080 > /dev/null do echo "Waiting for service..." sleep 2 done echo "Service is ready"
Loop Control Statements
break Statement
bash# Break out of loop for i in {1..10} do if [ $i -eq 5 ]; then break fi echo "Number: $i" done # Output: 1 2 3 4
continue Statement
bash# Skip current iteration for i in {1..10} do if [ $((i % 2)) -eq 0 ]; then continue fi echo "Odd number: $i" done # Output: 1 3 5 7 9
break and continue with Levels
bash# Break out of nested loops for i in {1..3} do for j in {1..3} do if [ $i -eq 2 ] && [ $j -eq 2 ]; then break 2 fi echo "i=$i, j=$j" done done
Practical Application Examples
bash#!/bin/bash # Example 1: Batch process files echo "Processing text files..." for file in *.txt do if [ -f "$file" ]; then echo "Processing: $file" # Add processing logic here cp "$file" "backup_$file" fi done # Example 2: Monitor process echo "Monitoring process..." while true do if ps aux | grep -q "[m]yprocess"; then echo "Process is running" else echo "Process stopped" break fi sleep 5 done # Example 3: Wait for multiple services services=("service1" "service2" "service3") for service in "${services[@]}" do echo "Waiting for $service..." until systemctl is-active --quiet "$service" do sleep 2 done echo "$service is ready" done # Example 4: Read configuration file echo "Reading configuration..." while IFS='=' read -r key value do # Skip comments and empty lines [[ $key =~ ^#.*$ ]] && continue [[ -z $key ]] && continue echo "Config: $key = $value" done < config.txt # Example 5: Parallel processing max_parallel=3 count=0 for task in task1 task2 task3 task4 task5 do # Start background task echo "Starting $task..." ( sleep 2 echo "$task completed" ) & count=$((count + 1)) # Control parallelism if [ $((count % max_parallel)) -eq 0 ]; then wait fi done wait echo "All tasks completed"
Loop Best Practices
- Quote variables: Prevent issues with spaces and special characters
- Set IFS for special delimiters:
IFS= read -r line - Use break and continue: Improve code readability
- Avoid infinite loops: Ensure while and until loops have exit conditions
- Use wait for background processes: Ensure all tasks complete
- Prefer C-style for loops: Clearer for number sequences
- Use array iteration:
for item in "${array[@]}"