【Linux】Shell编程入门
Shell概述
Shell是一个命令行解释器,它接收用户命令/应用程序,然后调用操作系统内核。Shell还是一个功能强大的编程语言,易编写、易调试和灵活性强等特点。
Shell 编程其它脚本语言一样,有一个能编写代码的文本编辑器和一个能解释执行的脚本解释器就可以了。
Linux 的 Shell 种类众多,常见的有:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
学习和工作中一般使用的bash比较多,本文也重在bash上,也就是Bourne Again Shell。
Shell变量
系统预定义变量
$HOME、 $PWD、 $SHELL、 $USER等
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $HOME
/root
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $PWD
/root
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $SHELL
/bin/bash
自定义变量
- 基本语法
- 定义变量:变量名=变量值,=号前后不能有空格
- 撤销变量:unset变量
- 声明静态变量:readonly变量,注意:不能unset
- 变量定义规则
- 变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
- 等号两侧不能有空格。
- 在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
- 变量的值如果有空格,需要使用单引号或者双引号括起来。
[root@iZ8vbglz44vvj8alpngy0bZ ~]# MY_NAME="ccc"
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $MY_NAME
ccc
[root@iZ8vbglz44vvj8alpngy0bZ ~]# unset MY_NAME
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $MY_NAME[root@iZ8vbglz44vvj8alpngy0bZ ~]# readonly MY_NAME
[root@iZ8vbglz44vvj8alpngy0bZ ~]# MY_NAME="ccc"
-bash: MY_NAME: readonly variable
特殊变量
$n
n为数字, $0代表该脚本名称,$1-9代表第一到第九的参数,十以上的参数需要用大括号包含,如 ${10}
#!/bin/bashecho "$0"echo "$1"
echo "$2"
[root@iZ8vbglz44vvj8alpngy0bZ ~]# sh test.sh 111 "c c"
test.sh
111
c c
$#
用于获取所有的输入个数,常用于循环。
#!/bin/bashecho "$0"echo "$1"
echo "$2"echo "$#"
[root@iZ8vbglz44vvj8alpngy0bZ ~]# sh test.sh 111 "c c"
test.sh
111
c c
2
$ * 和 $@
$* 表示命令行中的所有参数, $*把参数表示为一个整体
$@ 表示命令行中的所有参数, $@把每个参数区分对待
#!/bin/bashecho "$0"echo "$1"
echo "$2"echo "$#"
echo "$*"echo "$@"
[root@iZ8vbglz44vvj8alpngy0bZ ~]# sh test.sh 111 "c c"
test.sh
111
c c
2
111 c c
111 c c
运算符
$((运算式))或 $[运算式]
[root@iZ8vbglz44vvj8alpngy0bZ ~]# S=$[(2+3)*4]
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $S
20
条件判断
[ condition ] (condition前后要有空格)
注:条件非空即为true,[ cong ]返回true,[ ]返回false
常用条件:
- 两整数之间比较
-eq 等于 (equal)
-ne 不等于(not equal)
-lt 小于(less than)
-le 小于等于(less equal)
-gt 大于(greater than)
-ge 大于等于(greater equal)
- 按照文件权限进行判断
-r 有读的权限(read)
-w 有写的权限(write)
-x 有执行的权限(execute)
- 按照文件类型进行判断
-e 文件存在(existence)
-f 文件存在并且是一个常规的文件(file)
-d 文件存在并且是一个目录(directory)
[root@iZ8vbglz44vvj8alpngy0bZ ~]# [ 23 -ge 22 ]
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $?
0
[root@iZ8vbglz44vvj8alpngy0bZ ~]# ll
total 2276
-rw-r--r-- 1 root root 1394 Jul 28 19:37 a.txt
drwxr-xr-x 2 root root 4096 Mar 7 2024 cgroup-demo
drwxr-xr-x 3 root root 4096 Feb 14 2024 conf
drwxr-xr-x 9 systemd-coredump root 4096 Feb 25 2024 data
drwxr-xr-x 6 root root 4096 Feb 25 2024 hello
drwxr-xr-x 2 root root 4096 Feb 14 2024 logs
-rwxr-xr-x 1 root root 2294986 Aug 4 18:56 main
-rw------- 1 root root 89 Aug 11 16:43 nohup.out
-rw-r--r-- 1 root root 76 Aug 24 17:58 test.sh
[root@iZ8vbglz44vvj8alpngy0bZ ~]# [ -r a.txt ]
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $?
0
[root@iZ8vbglz44vvj8alpngy0bZ ~]# [ -e a.txt ]
[root@iZ8vbglz44vvj8alpngy0bZ ~]# echo $?
0
流程控制
if条件判断
if-else
if condition
then
command1
command2
…
commandN
fi
if else-if else
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
if [[ $1 -gt 100 ]]; then#statementsecho "第一个大于100"
elif [[ $1 -gt 50 ]]; then#statementsecho "第一个参数大于50"
elseecho "第一个参数小于等于50"
fi
case语句
case 值 in
模式1)
command1
command2
…
commandN
;;
模式2)
command1
command2
…
commandN
;;
esac
case $1 in"start" )echo "启动程序";;"stop" )echo "关闭程序";;"status" )echo "查看程序状态";;* )echo "输入的参数指令错误";;
esac
for循环
- 普通for
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
SUM=0
for (( i = 1; i <= 100; i++ )); do#statementsSUM=$[ $SUM + $i ]
done
echo $SUM
- for in
for var in item1 item2 … itemN do
command1
command2
…
commandN done
for i in $1; do#statementsecho "$i"
done
while 循环
while [条件判断式]
do
程序
done
SUM=1
while [ SUM -le 100 ]doSUM=$[ $SUM + 1 ]doneecho $SUM
read 读取控制台输入
read (选项) (参数)
选项:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)参数
变量:指定读取值的变量名
#在7秒内输入
read -t 7 -p "请输入您的姓名:" NAMEecho "你好 $NAME"
函数
系统函数
- basename
basename [string/pathname][suffix]
功能描述:basename命令会删除掉所有的前缀包括最后一个(/)字符,然后把字符串提取出来。
选项:
suffix 为后缀,如果suffix被指定了,basename会将pathname或string中的suffix去掉
[root@iZ8vbglz44vvj8alpngy0bZ logs]# basename /root/hello/logs/1.log
1.log
[root@iZ8vbglz44vvj8alpngy0bZ logs]# basename /root/hello/logs/1.log .log
1
- dirname
dirname 文件绝对路径
功能描述:从给定的包含绝对路径的文件名中去除文件名(非目录部分),然后返回剩下的路径(目录的部分)
[root@iZ8vbglz44vvj8alpngy0bZ logs]# dirname /root/hello/logs/1.log
/root/hello/logs
自定义函数
[ function ] funname [()]
{
action;[return int;]
}
注意:
- 所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。
- return 语句只能返回一个介于 0 到 255 之间的整数,而两个输入数字的和可能超过这个范围。
funWithParam(){echo "第一个参数为 $1 !"echo "第二个参数为 $2 !"echo "第十个参数为 $10 !"echo "第十个参数为 ${10} !"echo "第十一个参数为 ${11} !"echo "参数总数有 $# 个!"echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73