shell概述

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言(编程语言)。
微信图片_20220308201753.png
shell脚本一般以.sh为后缀

shell脚本格式及流程

1.脚本以 #!/bin/bash 开头
2.echo “输出语句”

3、第一种输出方式 (bash解析器执行)

①sh 脚本的相对路径
②sh 脚本的绝对路径

3.1、第二种输出方式 (linux直接执行)

①chmod +x 脚本名 赋予脚本的+x权限
② ./脚本名 相对路径执行
③ /绝对路径 绝对路径执行

shell变量

变量类型

运行shell时,会同时存在三种变量:

  1. 局部变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  2. 环境变量:所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  3. shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

    变量定义

    1.变量名可以由字母、数字、下划线组成,不能以数字开头,环境变量名大写
    2.等号两侧不能有空格
    3.变量的值有空格,需要使用双引号单引号括起

4.定义变量: 变量名=值
5.撤销变量: unset 变量名
6.使用变量: echo $变量名 或 echo ${变量名}
6.声明静态变量: readonly 变量名
7.提升变量为全局环境变量: export 变量名=值

  1. A=5
  2. B="ni hao"
  3. unset A
  4. echo $B
  5. readonly C=10
  6. export D="ni hao"

shell的注释

1.单行注释 #
2.多行注释: :<<!
被注释代码
!

字符串

单引号:

①被单引号括起来的任何字符都是普通字符(输出字面意思)
②单引号中不允许再出现单引号

双引号:

①双引号中忽视大部分特殊字符,但保留美元字符$反引号`反斜杠\
②双引号中的变量可以正常解释

“$”代表引用变量的值,而反引号代表引用命令

特殊变量

$0 : 固定,代表执行的文件名
$1 : 代表传入的第1个参数
$n : 代表传入的第n个参数
$#: 参数个数
$#: 传递到脚本的参数个数
$: 以一个单字符串显示所有向脚本传递的参数。如”$“用「”」括起来的情况、以”$1 $2 … $n”的形式输出所有参数
$@: 与$相同,但是使用时加引号,并在引号中返回每个参数。
$$: 脚本运行的当前进程号
$!: 后台运行的最后一个进程的ID
$?: 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
$
与 $@ 区别

  1. - 相同点:都是引用所有参数。
  2. - 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 123,,则 " * " 等价于 "1 2 3"(传递了一个参数),而 "@" 等价于 "1" "2" "3"(传递了三个参数)。

表达式

基本语法:

  1. $((运算符)) 或 $[运算符] 或者 expr m + n //expression 表达式
  2. 注意expr运算符间要有空格,如果希望将expr的结果赋给某个变量,使用``
  3. expr * , / , % 乘(需要转义),除 ,取余

    算数运算

    • 、-、*、\ : 乘号前必须加\进行转义才可以进行乘法运算
  • 加法运算

    • val=expr 2 + 2 (使用linux命令expr进行辅助运算)
    • val=$[2+2] (4个空格不是必要的,不同于条件判断)
    • val=$((2+2))

      数字关系运算符

      关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
      下面假定变量 a 为 10,变量 b 为 20
  • -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执行

    命令替换

    命令替换与变量替换差不多,都是用来重组命令行的,先完成引号里的命令行,然后将其结果替换出来,再重组成新的命令行。
    执行命令:
  1. ls /etc : 反引号 (所有的unix系统都支持)
  2. $(ls /etc) : $+() (部分unix系统不支持)
    多个嵌套使用时,从内向外执行for file in \s /etc\ 或 for file in $(ls /etc) 循环中使用
    dirname \$0 获取脚本文件所在的目录
    path=$(cd dirname $0;pwd) : 获取脚本当前所在目录,并且执行cd命令到达该目录,使用pwd获取路径并赋值到path变量

    算术运算

  3. $[ ] : 加减乘除,不必添加空格

  4. $(( )) :加减乘除等,不必添加空格

    逻辑判断

  5. [ ] : 中括号旁边和运算符两边必须添加空格 (可以使用,不推荐)

  6. [[ ]]:中括号旁边和运算符两边必须添加空格 (字符串验证时,推荐使用)
  7. (()) : 中括号旁边和运算符两边必须添加空格 (数字验证时,推荐使用)
  8. [[]] 和 (()) 分别是[ ]的针对数学比较表达式和字符串表达式的加强版。
  9. 使用[[ … ]]条件判断结构,而不是[ … ],能够防止脚本中的许多逻辑错误。比如,&&、||、<和> 操作符能够正常存在于[[ ]]条件判断结构中,但是如果出现在[ ]结构中的话,会报错。比如可以直接使用if [[ $a != 1 && $a != 2 ]], 如果不适用双括号, 则为if [ $a -ne 1] && [ $a != 2 ]或者if [ $a -ne 1 -a $a != 2 ]。
    [[ ]]中增加模式匹配特效;
    (( ))不需要再将表达式里面的大小于符号转义,除了可以使用标准的数学运算符外,还增加了以下符号

image.png

read键盘录入

Java中获取用户输入可以使用Scanner类实现,linux中使用read命令即可实现
1.读取键盘输入

  1. #!/bin/bash
  2. echo "请输入用户名:"
  3. read name
  4. echo "用户名:$name"
  5. echo "---------------------------------"
  6. read -p 请输入第一个数字: first
  7. read -p 请输入第二个数字: second
  8. let c=first+second
  9. echo "和:$c"

3.读取文件里的内容

  1. #!/bin/bash
  2. while read line
  3. do
  4. echo $line
  5. sleep 2
  6. 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位小数。
  • 转义符:

    • \a :警告字符,通常为ASCII的BEL字符
    • \b :后退
    • \c :抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
    • \f :换页(formfeed)
    • \n :换行
    • \r :回车(Carriage return)
    • \t :水平制表符
    • \v :垂直制表符
    • \ :一个字面上的反斜杠字符
    • \ddd :表示1到3位数八进制值的字符。仅在格式字符串中有效
    • \0ddd :表示1到3位的八进制值字符

      流程控制

  • if判断

1)基本语法 单分支

if [ 条件判断式 ];then
程序
fi

if [ 条件判断式 ] then
程序
fi

或者 多分支
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
注意事项:
(1)[ 条件判断式 ],中括号和条件判断式之间必须有空格
(2)if后要有空格

案例:

  1. #!/bin/bash
  2. if [ $1 -eq "1" ]
  3. then
  4. echo "111"
  5. elif [ $1 -eq "2" ]
  6. then
  7. echo "222"
  8. fi
  • Case in

类比Java中的switch结构,可以实现等值判断

  1. 语法:
  2. case 表达式 in
  3. 1)
  4. 语句1
  5. ;; #等同于switch语句中的break
  6. 2)
  7. 语句2
  8. ;; #等同于switch语句中的break
  9. *) #等同于switch语句中的default
  10. 语句N
  11. esac
  1. printf "Input integer number: "
  2. read num
  3. case $num in
  4. 1)
  5. echo "Monday"
  6. ;;
  7. 2)
  8. echo "Tuesday"
  9. ;;
  10. 3)
  11. echo "Wednesday"
  12. ;;
  13. 4)
  14. echo "Thursday"
  15. ;;
  16. 5)
  17. echo "Friday"
  18. ;;
  19. 6)
  20. echo "Saturday"
  21. ;;
  22. 7)
  23. echo "Sunday"
  24. ;;
  25. *)
  26. echo "error"
  27. esac
  • for循环

for (( 初始值;循环控制条件;变量变化 ))

do

程序

done

案例

  1. #!/bin/bash
  2. s=0
  3. for((i=0;i<=100;i++))
  4. do
  5. s=$[$s+$i]
  6. done
  7. echo $s

for 变量 in 值1 值2 值3…

do

程序

done

案例

  1. #!/bin/bash
  2. #打印数字
  3. for i in 1 2 3
  4. do
  5. echo "ni hao $i"
  6. done

数组

数组格式

方式1:arr=()
方式2: arr=(value1 value2 value3) (这种方式带值)
注意:往数组里添加值,数组的长度自动增长
获取数组的长度:${#arr[*]}

遍历数组

  1. #!/bin/bash
  2. arr=(10 20 30)
  3. for i in ${arr[*]};
  4. do
  5. echo $i
  6. done
  7. echo "-------------------"
  8. arr[0]=100
  9. arr[1]=200
  10. arr[2]=300
  11. for i in ${arr[*]};
  12. do
  13. echo $i
  14. done
  15. echo "数组长度:${#arr[*]}"
  16. echo "----------------------"
  17. length=${#arr[*]}
  18. j=0
  19. while ((j<length));
  20. do
  21. echo "j=$j"
  22. echo ${arr[j]}
  23. let j++
  24. done

函数

自定义函数

  1. #定义函数
  2. function 函数名(){
  3. # 通过$1获取传递的参数值
  4. return #如果没有写return,会将最后的执行代码作为返回结果
  5. }
  6. 函数名 10 20
  7. $?

系统函数

  1. basename
  2. 概念: 根据给定的路径,获取路径的文件名
  3. 用法: basename /root/a/b/a.txt 输出: a.txt
  4. dirname
  5. 概念: 根据给定的路径,获取路径中的绝对路径
  6. 用法:dirname /root/a/b/a.txt 输出: /root/a/b