shell概述
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言(编程语言)。
shell脚本一般以.sh为后缀
shell脚本格式及流程
1.脚本以 #!/bin/bash 开头
2.echo “输出语句”
3、第一种输出方式 (bash解析器执行)
3.1、第二种输出方式 (linux直接执行)
①chmod +x 脚本名 赋予脚本的+x权限
② ./脚本名 相对路径执行
③ /绝对路径 绝对路径执行
shell变量
变量类型
运行shell时,会同时存在三种变量:
- 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
变量定义
1.变量名可以由字母、数字、下划线组成,不能以数字开头,环境变量名大写
2.等号两侧不能有空格
3.变量的值有空格,需要使用双引号或单引号括起
4.定义变量: 变量名=值
5.撤销变量: unset 变量名
6.使用变量: echo $变量名 或 echo ${变量名}
6.声明静态变量: readonly 变量名
7.提升变量为全局环境变量: export 变量名=值
A=5
B="ni hao"
unset A
echo $B
readonly C=10
export D="ni hao"
shell的注释
字符串
单引号:
①被单引号括起来的任何字符都是普通字符(输出字面意思)
②单引号中不允许再出现单引号
双引号:
①双引号中忽视大部分特殊字符,但保留美元字符$,反引号`和反斜杠\
②双引号中的变量可以正常解释
“$”代表引用变量的值,而反引号代表引用命令
特殊变量
$0 : 固定,代表执行的文件名
$1 : 代表传入的第1个参数
$n : 代表传入的第n个参数
$#: 参数个数
$#: 传递到脚本的参数个数
$: 以一个单字符串显示所有向脚本传递的参数。如”$“用「”」括起来的情况、以”$1 $2 … $n”的形式输出所有参数
$@: 与$相同,但是使用时加引号,并在引号中返回每个参数。
$$: 脚本运行的当前进程号
$!: 后台运行的最后一个进程的ID
$?: 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
$ 与 $@ 区别
- 相同点:都是引用所有参数。
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。
表达式
基本语法:
- $((运算符)) 或 $[运算符] 或者 expr m + n //expression 表达式
- 注意expr运算符间要有空格,如果希望将expr的结果赋给某个变量,使用``
- expr * , / , % 乘(需要转义),除 ,取余
算数运算
- 、-、*、\ : 乘号前必须加\进行转义才可以进行乘法运算
加法运算
-eq :检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。
- -ne: 检测两个数是否不相等,不相等返回 true。 [ $a -ne $b ] 返回 true。
- -gt: 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。
- -lt : 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。
- -ge: 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。
-le : 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。
字符串运算符
下表列出了常用的字符串运算符,假定变量 a 为 “abc”,变量 b 为 “efg”:
= :检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
- != :检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。
- -z :检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。
- -n :检测字符串长度是否为0,不为0返回 true。 [ -n “$a” ] 返回 true。
$ :检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。
布尔运算符
下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:
- ! :非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。
- -o :或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a :与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。
逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:
&& :逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| :逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true
文件运算符
-b file :检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。
- -c file :检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ] 返回 false。
- -d file :检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
- -f file :检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。
- -g file :检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。
- -k file :检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。
- -p file :检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ] 返回 false。
- -u file :检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。
- -r file :检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。
- -w file :检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。
- -x file :检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。
- -s file :检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。
- -e file :检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。
shell执行
命令替换
命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
执行命令:
ls /etc
: 反引号 (所有的unix系统都支持)$(ls /etc) : $+() (部分unix系统不支持)
多个嵌套使用时,从内向外执行for file in \s /etc\ 或 for file in $(ls /etc) 循环中使用dirname \$0
获取脚本文件所在的目录
path=$(cddirname $0
;pwd) : 获取脚本当前所在目录,并且执行cd命令到达该目录,使用pwd获取路径并赋值到path变量算术运算
$[ ] : 加减乘除,不必添加空格
-
逻辑判断
[ ] : 中括号旁边和运算符两边必须添加空格 (可以使用,不推荐)
- [[ ]]:中括号旁边和运算符两边必须添加空格 (字符串验证时,推荐使用)
- (()) : 中括号旁边和运算符两边必须添加空格 (数字验证时,推荐使用)
- [[]] 和 (()) 分别是[ ]的针对数学比较表达式和字符串表达式的加强版。
- 使用[[ … ]]条件判断结构,而不是[ … ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
[[ ]]中增加模式匹配特效;
(( ))不需要再将表达式里面的大小于符号转义,除了可以使用标准的数学运算符外,还增加了以下符号
read键盘录入
Java中获取用户输入可以使用Scanner类实现,linux中使用read命令即可实现
1.读取键盘输入
#!/bin/bash
echo "请输入用户名:"
read name
echo "用户名:$name"
echo "---------------------------------"
read -p 请输入第一个数字: first
read -p 请输入第二个数字: second
let c=first+second
echo "和:$c"
3.读取文件里的内容
#!/bin/bash
while read line
do
echo $line
sleep 2
done < /test/aa.txt
输出
echo
仅用于字符串的输出,没有使用printf作为输出的移植性好,建议使用printf
printf
printf 不会像 echo 自动添加换行符,我们可以手动添加 \n
无大括号,直接以空格分隔
- 格式:printf format-string [arguments…] 其中(format-string: 格式控制字符串、arguments: 参数列表)
- 案例:printf “%-10s %-8s %-4.2f\n” 郭靖 男 66.1234
- %s %c %d %f 都是格式替代符
- d:Decimal 十进制整数 对应位置参数必须是十进制整数,否则报错!
- s:String 字符串 对应位置参数必须是字符串或者字符型 否则报错
- c:Char 字符 对应位置参数必须是字符串或者字符型 否则报错
- f:Float 浮点 对应位置参数必须是数字型 否则报错
- %-10s : 指一个宽度为10个字符(-表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。
- %-4.2f :指格式化为小数,宽度为4个字符,其中.2指保留2位小数。
转义符:
if判断
1)基本语法 单分支
if [ 条件判断式 ];then
程序
fiif [ 条件判断式 ] then
程序
fi或者 多分支
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格
案例:
#!/bin/bash
if [ $1 -eq "1" ]
then
echo "111"
elif [ $1 -eq "2" ]
then
echo "222"
fi
- Case in
类比Java中的switch结构,可以实现等值判断
语法:
case 表达式 in
值1)
语句1
;; #等同于switch语句中的break
值2)
语句2
;; #等同于switch语句中的break
*) #等同于switch语句中的default
语句N
esac
printf "Input integer number: "
read num
case $num in
1)
echo "Monday"
;;
2)
echo "Tuesday"
;;
3)
echo "Wednesday"
;;
4)
echo "Thursday"
;;
5)
echo "Friday"
;;
6)
echo "Saturday"
;;
7)
echo "Sunday"
;;
*)
echo "error"
esac
- for循环
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
案例
#!/bin/bash
s=0
for((i=0;i<=100;i++))
do
s=$[$s+$i]
done
echo $s
for 变量 in 值1 值2 值3…
do
程序
done
案例
#!/bin/bash
#打印数字
for i in 1 2 3
do
echo "ni hao $i"
done
数组
数组格式
方式1:arr=()
方式2: arr=(value1 value2 value3) (这种方式带值)
注意:往数组里添加值,数组的长度自动增长
获取数组的长度:${#arr[*]}
遍历数组
#!/bin/bash
arr=(10 20 30)
for i in ${arr[*]};
do
echo $i
done
echo "-------------------"
arr[0]=100
arr[1]=200
arr[2]=300
for i in ${arr[*]};
do
echo $i
done
echo "数组长度:${#arr[*]}"
echo "----------------------"
length=${#arr[*]}
j=0
while ((j<length));
do
echo "j=$j"
echo ${arr[j]}
let j++
done
函数
自定义函数
#定义函数
function 函数名(){
# 通过$1获取传递的参数值
return #如果没有写return,会将最后的执行代码作为返回结果
}
函数名 10 20
$?
系统函数
basename
概念: 根据给定的路径,获取路径的文件名
用法: basename /root/a/b/a.txt 输出: a.txt
dirname
概念: 根据给定的路径,获取路径中的绝对路径
用法:dirname /root/a/b/a.txt 输出: /root/a/b