在Shell脚本中,case语句是一种多路选择结构,它允许一个变量等于多个值时分别执行不同的操作。case语句以case
关键字开始,以esac
(case的反写)关键字结束。
以下是一个基本的case语句的示例:
case $variable in
pattern1)
command1
command2
;;
pattern2)
command3
command4
;;
esac
在这个例子中,$variable
是我们要检查的变量,pattern1
和pattern2
是我们要匹配的模式,command1
,command2
,command3
和command4
是我们在匹配成功时要执行的命令。;;
用于表示某个模式的结束。
在case语句中,我们也可以使用通配符(*)来匹配任意的字符。以下是一个使用通配符的case语句的示例:
case $variable in
*.txt)
echo "This is a text file."
;;
*.jpg|*.png)
echo "This is an image file."
;;
*)
echo "Unknown file type."
;;
esac
在这个例子中,我们用*.txt
来匹配所有的文本文件,用*.jpg|*.png
来匹配所有的JPG和PNG图片,用*
来匹配所有其他的文件类型。
在Shell脚本中,当存在许多可能的选项,且根据这些选项需要执行不同的操作时,case语句就非常有用。例如,在交互式脚本中,我们可以使用case语句来处理用户输入:
echo "Enter your choice: "
read choice
case $choice in
1)
echo "You chose option 1."
;;
2)
echo "You chose option 2."
;;
*)
echo "Invalid option."
;;
esac
另一个case语句的重要应用是模式匹配。如前文所述,我们可以使用通配符来匹配多种模式。这在处理文件时尤其有用,例如,我们可以根据文件扩展名来执行不同的操作:
file="example.txt"
case $file in
*.txt)
echo "This is a text file."
;;
*.jpg)
echo "This is a JPG file."
;;
*)
echo "Unknown file type."
;;
esac
case语句相比if-elif-else结构的一个主要优点是它更加清晰和直观。当有许多可能的选项时,使用case语句可以使代码更易读,更易维护。此外,由于case语句是按顺序逐一检查每个模式,所以它的执行效率通常比if-elif-else结构更高。
在这个简单的例子中,我们将用case语句处理用户的输入。我们使用的模式是 [yY] | [yY][eE][sS]
和 [nN] | [nN][oO]
,这意味着无论用户输入的是大写还是小写的 ‘yes’ 或 ‘no’,我们的脚本都可以正确地处理。
echo "Please enter yes or no: "
read answer
case $answer in
[yY] | [yY][eE][sS])
echo "You answered YES."
;;
[nN] | [nN][oO])
echo "You answered NO."
;;
*)
echo "Invalid input."
;;
esac
在这个例子中,我们将用case语句处理脚本的命令行参数。$1
代表脚本的第一个参数,根据这个参数的值,我们执行不同的操作。
case $1 in
start)
echo "Starting the service..."
;;
stop)
echo "Stopping the service..."
;;
restart)
echo "Restarting the service..."
;;
*)
echo "Invalid command. Please use start, stop, or restart."
;;
esac
在这个例子中,我们将用case语句创建一个简单的菜单。根据用户的输入,我们执行不同的操作。
echo "1. Start"
echo "2. Stop"
echo "3. Restart"
echo "Please enter your choice: "
read choice
case $choice in
1)
echo "Starting..."
;;
2)
echo "Stopping..."
;;
3)
echo "Restarting..."
;;
*)
echo "Invalid choice."
;;
esac
在这个例子中,我们将用case语句根据文件类型执行不同的操作。我们通过检查文件的扩展名来确定文件的类型。
file="example.txt"
case $file in
*.txt)
echo "Opening the text file..."
;;
*.jpg)
echo "Opening the JPG file..."
;;
*.png)
echo "Opening the PNG file..."
;;
*)
echo "Unknown file type."
;;
esac
在这个例子中,我们将用case语句处理系统发出的信号。当我们的脚本接收到 SIGINT
或 SIGTERM
信号时,我们打印一条相应的消息。
trap 'case $1 in
SIGINT)
echo "You pressed Ctrl+C!"
;;
SIGTERM)
echo "Terminating the script..."
exit 1
;;
esac' SIGINT SIGTERM
在这个例子中,我们将用case语句处理文件的扩展名。我们遍历当前目录下的所有文件,并根据文件的扩展名执行不同的操作。
for file in *
do
case $file in
*.txt)
echo "$file is a text file."
;;
*.docx)
echo "$file is a Word document."
;;
*.jpg)
echo "$file is a JPG image."
;;
*.png)
echo "$file is a PNG image."
;;
*)
echo "$file is an unknown type."
;;
esac
done
在这个例子中,我们将用case语句处理脚本的选项。getopts
函数用于处理命令行选项,$opt
变量存储当前的选项字符。
while getopts ":a:b:c" opt; do
case $opt in
a) a_arg="$OPTARG"
;;
b) b_arg="$OPTARG"
;;
c) c_arg=1
;;
\?) echo "Invalid option -$OPTARG" >&2
;;
esac
done
在这个例子中,我们将用case语句根据文件的修改时间创建备份。$(date +%m -r $file)
可以获取文件的最后修改月份,然后我们根据月份将文件复制到对应的目录。
for file in *
do
case $(date +%m -r $file) in
01|02|03)
mkdir -p Q1
cp $file Q1/
;;
04|05|06)
mkdir -p Q2
cp $file Q2/
;;
07|08|09)
mkdir -p Q3
cp $file Q3/
;;
10|11|12)
mkdir -p Q4
cp $file Q4/
;;
esac
done
在这个例子中,我们将用case语句处理系统的日志文件。我们首先使用 grep
命令从系统日志中提取出含有 ‘error’ 的行,然后使用 case 语句根据错误的类型打印不同的消息。
grep 'error' /var/log/syslog | while read errorline
do
case $errorline in
*network*)
echo "Network error: $errorline"
;;
*disk*)
echo "Disk error: $errorline"
;;
*)
echo "Unknown error: $errorline"
;;
esac
done
在这个例子中,我们将用case语句模拟一个状态机。我们有一个变量 state
,根据它的值,我们执行不同的操作并更新它的值。
state="start"
while true
do
case $state in
start)
echo "Starting..."
state="run"
;;
run)
echo "Running..."
state="stop"
;;
stop)
echo "Stopping..."
state="start"
;;
esac
done