shell脚本实践

参考:菜鸟教程
shell在线编辑器

linux 常见目录名称
在这里插入图片描述

shell是什么?

  • 一个用C语言编写的程序
  • 一种命令语言,一种程序设计语言
  • Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务

Shell 编程跟 JavaScript、php 编程一样,一个能编写代码的文本编辑器和一个能解释执行的脚本解释器

变量、语法

# 1.Shell变量 

# 命名
# - 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
# - 中间不能有空格,可以使用下划线 _。
# - 不能使用标点符号。
# - 不能使用bash里的关键字(可用help命令查看保留关键字)

# 使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
your_name="转身之后"
echo your_name 
#Shell 的 echo 指令与 PHP 的 echo 指令类似,都是用于字符串的输出。

#变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界
echo  ${your_name}

# for 循环 
for file in `ls /`;do
  echo "${file}"

done

# 只读变量 readonly 
# 使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
# myUrl="https://www.google.com"
# readonly myUrl
# myUrl="https://www.runoob.com"
# /bin/sh: NAME: This variable is read only.

# 删除变量 unset
#使用 unset 命令可以删除变量。语法 变量被删除后不能再次使用。unset 命令不能删除只读变量。
unset variable_name

myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl
#以上实例执行将没有任何输出。

# 变量类型
# 剧本变量 环境变量 shell变量



# Shell字符串
# 字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。
str='this is a string'
# 单引号字符串的限制:

# 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
# 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用。

#双引号
your_name="runoob"
str="Hello, I know you are \"$your_name\"! \n"
echo -e $str 
#  -e 开启转义
# Hello, I know you are "runoob"! 
# 双引号的优点:
# 双引号里可以有变量
# 双引号里可以出现转义字符

# 获取字符串长度
string="你的名字"
echo ${#string}   # 输出 4

# 查找子字符串
# 查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
string="runoob is a great site"
echo `expr index "$string" io`  # 输出 4

# Shell 数组
# 定义数组
# 在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
# 数组名=(值1 值2 ... 值n)
array_name=('value0' 'value1' 'value2' 'value3')
# array_name[0]=value0
# array_name[1]=value1
# array_name[n]=valuen

# 读取数组
# 读取数组元素值的一般格式是:
# ${数组名[下标]} valuen=${array_name[n]}

# 使用 @ 符号可以获取数组中的所有元素,例如:
echo ${array_name[0]}
echo ${array_name[@]}

# 获取数组的长度
# 取得数组元素的个数
echo ${#array_name[@]}
# 或者
echo ${#array_name[*]}
# 取得数组单个元素的长度
echo ${#array_name[n]}

# 关联数组
# 数组是一种用于存储一组相同类型元素的数据结构,关联数组是一种支持将任意类型的值与某个键关联起来的数据结构,在 Bash 中可以使用字符串作为关联数组的键

# 关联数组使用 declare 命令来声明,语法格式如下:
# declare -A array_name

declare -A site=(["google"]="www.google.com" ["runoob"]="www.runoob.com" ["taobao"]="www.taobao.com")
# 我们也可以先声明一个关联数组,然后再设置键和值:
# declare -A site
# site["google"]="www.google.com"
# site["runoob"]="www.runoob.com"
# site["taobao"]="www.taobao.com"

echo ${site["runoob"]}

echo "数组的元素为: ${site[*]}"
# echo "数组的元素为: ${site[@]}"
# 在数组前加一个感叹号 ! 可以获取数组的所有键,例如:
echo "数组的键为: ${!site[*]}"




:<<EOF
注释内容...
注释内容...
注释内容...
EOF

# Shell 基本运算符
# 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。

val=`expr 2 + 2`
echo "两数之和为 : $val"

# 两点注意:

# 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
# 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

a=10
b=20

val=`expr $a + $b`
echo "a + b: ${val}"

val=`expr $a - $b`
echo "a - b : $val"

val=`expr $a \* $b`
echo "a * b : $val"

val=`expr $b / $a`
echo "b / a : $val"

val=`expr $b % $a`
echo "b % a : $val"

if [ $a == $b ]
then 
echo "a=b"
fi
if [ $a != $b ]
then 
echo "a=b"
fi
# 乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
# if...then...fi 是条件语句,后续将会讲解。



## 关系运算符
# 关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

# 下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

a=10
b=20

if [ $a -eq $b]
then
   echo "$a -eq $b : a 等于 b"
else
   echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
   echo "$a -ne $b: a 不等于 b"
else
   echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
   echo "$a -gt $b: a 大于 b"
else
   echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
   echo "$a -lt $b: a 小于 b"
else
   echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
   echo "$a -ge $b: a 大于或等于 b"
else
   echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
   echo "$a -le $b: a 小于或等于 b"
else
   echo "$a -le $b: a 大于 b"
fi

## 布尔运算符
# 下表列出了常用的布尔运算符,假定变量 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。
# !	非运算,表达式为 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。
a=10
b=20

if [ $a != $b ]
then
   echo "$a != $b : a 不等于 b"
else
   echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
   echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
   echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
   echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
   echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
   echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
   echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi

# 逻辑运算符
# &&	逻辑的 AND	[[ $a -lt 100 && $b -gt 100 ]] 返回 false
# ||	逻辑的 OR	[[ $a -lt 100 || $b -gt 100 ]] 返回 true

a=10
b=20

if [[ $a -lt 100 && $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

if [[ $a -lt 100 || $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

# 字符串运算符
# 表列出了常用的字符串运算符,假定变量 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。
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

a="abc"
b="efg"

if [ $a = $b ]
then
   echo "$a = $b : a 等于 b"
else
   echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
   echo "$a != $b : a 不等于 b"
else
   echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
   echo "-z $a : 字符串长度为 0"
else
   echo "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ]
then
   echo "-n $a : 字符串长度不为 0"
else
   echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
   echo "$a : 字符串不为空"
else
   echo "$a : 字符串为空"
fi

# 文件测试运算符
# 文件测试运算符用于检测 Unix 文件的各种属性
# 属性检测描述如下:
# -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。


file="/home/runner/LightheartedAlarmingPresses/main.sh"
if [ -r $file ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi
if [ -w $file ]
then
   echo "文件可写"
else
   echo "文件不可写"
fi
if [ -x $file ]
then
   echo "文件可执行"
else
   echo "文件不可执行"
fi
if [ -f $file ]
then
   echo "文件为普通文件"
else
   echo "文件为特殊文件"
fi
if [ -d $file ]
then
   echo "文件是个目录"
else
   echo "文件不是个目录"
fi
if [ -s $file ]
then
   echo "文件不为空"
else
   echo "文件为空"
fi
if [ -e $file ]
then
   echo "文件存在"
else
   echo "文件不存在"
fi

# echo  

# 3.显示变量
# read 命令从标准输入中读取一行,并把输入行的每个字段的值指定给 shell 变量
# read name 
# echo "$name It is a test"

# 显示结果定向至文件
echo "It is a test" > myfile
# 原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'

# 显示命令执行结果,这里使用的是反引号 `, 而不是单引号 '。
echo `date`

# printf命令

# %s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。

# %-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。

# %-4.2f 指格式化为小数,其中 .2 指保留2位小数。

printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg  
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

#test命令
# Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
num1=100
num2=100
if test $[num1] -eq $[num2]
then
    echo '两个数相等!'
else
    echo '两个数不相等!'
fi
# 代码中的 [] 执行基本的算数运算

num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
    echo '两个字符串相等!'
else
    echo '两个字符串不相等!'
fi

cd /bin
if test -e ./bash
then
    echo '文件已存在!'
else
    echo '文件不存在!'
fi

# 流程控制
# sh 的流程控制不可为空

# if 
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi

# if  
# if condition
# then
#     command1 
#     command2
#     ...
#     commandN 
# fi


# if else 
# if condition
# then
#     command1 
#     command2
#     ...
#     commandN
# else
#     command
# fi

# if else if 
# if condition1
# then
#     command1
# elif condition2 
# then 
#     command2
# else
#     commandN
# fi

a=20
b=25
if [ $a == $b ]
then 
  echo "a等于b"
elif [ $a -gt $b ]
then 
  echo "a>于b"
else
  echo "其他"
fi


#for循环

# for var in item1 item2 ... itemN
# do
#     command1
#     command2
#     ...
#     commandN
# done

# for 
# 当变量值在列表里,for 循环即执行一次所有命令,使用变量名获取列表中的当前取值。命令可为任何有效的 shell 命令和语句。in 列表可以包含替换、字符串和文件名。

# in列表是可选的,如果不用它,for循环使用命令行的位置参数。
# 顺序输出当前列表中的数字:
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

# while 语句
# while 循环用于不断执行一系列命令,也用于从输入文件中读取数据。其语法格式为:

# while condition
# do
#     command
# done

 
int=1
while(( $int<=5 )) # true /:
do
    echo $int
    let "int++"
    # 以上实例使用了 Bash let 命令,它用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量
done

# until 循环
# until 循环执行一系列命令直至条件为 true 时停止。

# until condition
# do
#     command
# done
a=0

until [ ! $a -lt 10 ]
do
   echo $a
   a=`expr $a + 1`
done

# case ... esac
# case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。

# 可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。

# case ... esac 语法格式如下:

# case 值 in
# 模式1)
#     command1
#     command2
#     ...
#     commandN
#     ;;
# 模式2)
#     command1
#     command2
#     ...
#     commandN
#     ;;
# esac


site="runoob"

case "$site" in
   "runoob") echo "菜鸟教程"
   ;;
   "google") echo "Google 搜索"
   ;;
   "taobao") echo "淘宝网"
   ;;
esac

# 跳出循环
# 在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:break 和 continue。

# shell函数
# linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。

# shell中函数的定义格式如下:

# [ function ] funname [()]

# {

#     action;

#     [return int;]

# }
# 说明:

# 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
# 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255

demoFun(){
echo "等闲变却故人心 "
}
demoFun

# 下面定义一个带有return语句的函数:
funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum$anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
# 函数返回值在调用该函数后通过 $? 来获得

# 输出重定向
# 重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:

# command1 > file1
# 执行后,并没有在终端输出信息,这是因为输出已被从默认的标准输出设备(终端)重定向到指定的文件。
# 输出重定向会覆盖文件内容

# 如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾

# 输入重定向
# 注意:输出重定向是大于号(>),输入重定向是小于号(<)。

# 重定向深入讲解
# 一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

# 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
# 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
# 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

# 2>&1 & 表示将标准错误输出重定向到标准输出的位置,并将程序放在后台运行








参数

# 我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……

# 以下实例我们向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径):

echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";

# $#	传递到脚本的参数个数
# $*	以一个单字符串显示所有向脚本传递的参数。
# 如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
# $$	脚本运行的当前进程ID号
# $!	后台运行的最后一个进程的ID号
# $@	与$*相同,但是使用时加引号,并在引号中返回每个参数。
# 如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
# $-	显示Shell使用的当前选项,与set命令功能相同。
# $?	显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

echo "Shell 传递参数实例!";
echo "第一个参数为:$1";

echo "参数个数为:$#";
echo "传递的参数作为一个字符串显示:$*";

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


echo "-- \$* 演示 ---"
for i in "$*"; do
    echo $i
done

echo "-- \$@ 演示 ---"
for i in "$@"; do
    echo $i
done

# $10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。


 

脚本

#! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell

运行shell脚本有两种方法

1.作为可执行程序

chmod +x ./test.sh  #使脚本具有执行权限
./test.sh  #执行脚本

2.作为解释器参数

直接运行解释器,其参数就是 shell 脚本的文件名

/bin/sh test.sh

shell变量

定义变量:

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  • 中间不能有空格,可以使用下划线 _
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。

显示赋值

变量名=值

语句给变量赋值

将 /etc 下目录的文件名循环出来:

for file in `ls /etc`
或
for file in $(ls /etc)

使用变量

使用一个定义过的变量,只要在变量名前面加美元符号即可

your_name="qinjx"
echo $your_name
echo ${your_name}

变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界

只读变量

使用 readonly 命令可以将变量定义为只读变量

删除变量

使用 unset 命令可以删除变量。语法:

unset variable_name

变量类型

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

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

shell字符串

字符串可以用单引号,也可以用双引号,也可以不用引号。

获取字符串长度

string="abcd"
echo ${#string}  *# 输出 4*

变量为数组时,KaTeX parse error: Expected '}', got '#' at position 2: {#̲string}** 等价于 *…{#string[0]}:

提取子字符串

从字符串第 2 个字符开始截取 4 个字符:

string="runoob is a great site"
echo ${string:1:4} # 输出 unoo

查找子字符串

查找字符 io 的位置(哪个字母先出现就计算哪个):

string="runoob is a great site"
echo `expr index "$string" io`  # 输出 4

shell数组

bash支持一维数组,且没有限定数组的大小

定义数组

在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:

数组名=(值1 值2 ... 值n)

读取数组

读取数组元素值的一般格式是:

${数组名[下标]}

例如:

valuen=${array_name[n]}

使用 @ 符号可以获取数组中的所有元素,例如:

echo ${array_name[@]}

获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,例如:

# 取得数组元素的个数*
length=${#array_name[@]}
# 或者*
length=${#array_name[*]}
# 取得数组单个元素的长度*
lengthn=${#array_name[n]}

Shell 注释

# 开头的行就是注释,会被解释器忽略

多行注释

多行注释还可以使用以下格式:

:<<EOF
注释内容...
注释内容...
注释内容...
EOF

shell传递参数

执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$nn 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……

$0 为执行的文件名(包含文件路径)

另外,还有几个特殊字符用来处理参数:

参数处理说明
$#传递到脚本的参数个数
$*以一个单字符串显示所有向脚本传递的参数。 如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@ ∗ 相同,但是使用时加引号,并在引号中返回每个参数。如 " *相同,但是使用时加引号,并在引号中返回每个参数。 如" 相同,但是使用时加引号,并在引号中返回每个参数。如"@“用「”」括起来的情况、以"$1" “ 2 " … " 2" … " 2""n” 的形式输出所有参数。
$-显示Shell使用的当前选项,与set命令功能相同。
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

基本运算符

原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

两点注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

算术运算符

**注意:**条件表达式要放在方括号之间,并且要有空格,例如: [ a = = a== a==b] 是错误的,必须写成 [ $a == $b ]

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

下表列出了常用的关系运算符,假定变量 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 为 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

字符串运算符

列出了常用的字符串运算符,假定变量 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。

文件测试运算符

文件测试运算符用于检测 Unix 文件的各种属性。

属性检测描述如下:

操作符说明举例
-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。
-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。
-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。

echo

用于字符串的输出

echo string

显示命令执行结果

结果将显示当前日期

echo `date`

这里使用的是反引号 `, 而不是单引号

Shell 的另一个输出命令 printf

printf 使用引用文本或空格分隔的参数,外面可以在 printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n

printf  format-string  [arguments...]

参数说明:

  • format-string: 为格式控制字符串
  • arguments: 为参数列表。

%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。

%-10s 指一个宽度为 10 个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在 10 个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来。

%-4.2f 指格式化为小数,其中 .2 指保留2位小数。

printf 的转义序列

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

test命令

于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

流程控制

if else

fi

if 语句语法格式:

if condition
then
    command1 
    command2
    ...
    commandN 
fi
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi

if else

if else 语法格式:

if condition
then
    command1 
    command2
    ...
    commandN
else
    command
fi

if else-if else

if else-if else 语法格式:

if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

for循环

for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done
for var in item1 item2 ... itemN; do command1; command2… done;

while语句

while 循环用于不断执行一系列命令,也用于从输入文件中读取数据。其语法格式为:

while condition
do
    command
done

无限循环语法格式:

while :
do
    command
done

until 循环

until 循环执行一系列命令直至条件为 true 时停止。

until 循环与 while 循环在处理方式上刚好相反。

一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。

until 语法格式:

until condition
do
    command
done

case…esac

case … esac 为多选择语句,与其他语言中的 switch … case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case … esac 语句,esac(就是 case 反过来)作为结束标记。

可以用 case 语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。

case … esac 语法格式如下:

case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
esac

跳出循环

在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:breakcontinue

break 命令

break 命令允许跳出所有循环(终止执行后面的所有循环)。

continue

continue 命令与 break 命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。

练习

从日志文件中读取数据并处理



#!/bin/bash 
# redirecting file input
exec 0< testfile 
count=1 
while read line 
do 
 echo "Line #$count: $line" 
 count=$[ $count + 1 ] 
done


shell脚本使用命令行参数指定待读取的.csv文件

#!/bin/bash 
# read file and create INSERT statements for MySQL 
outfile='members.sql' 
IFS=',' 
while read lname fname address city state zip 
do 
 cat >> $outfile << EOF 
 INSERT INTO members (lname,fname,address,city,state,zip) VALUES 
('$lname', '$fname', '$address', '$city', '$state', '$zip'); 
EOF 
done < ${1}


使用trap命令来忽略SIGINT信号,并控制脚本的行为



#!/bin/bash 
# Testing signal trapping 
# 
trap "echo ' Sorry! I have trapped Ctrl-C'" SIGINT 
# 
echo This is a test script 
# 
count=1 
while [ $count -le 10 ] 
do 
 echo "Loop #$count" 
 sleep 1 
 count=$[ $count + 1 ] 
done 
# 
echo "This is the end of the test script" 
#

在这里插入图片描述

要捕获shell脚本的退出,只要在trap命令后加上EXIT信号就行

#!/bin/bash 
# Trapping the script exit 
# 
trap "echo Goodbye..." EXIT 
# 
count=1 
while [ $count -le 5 ] 
do 
 echo "Loop #$count" 
 sleep 1 
 count=$[ $count + 1 ] 
done 
# 
$

在这里插入图片描述

作业

at 获取作业的输出 在脚本中对STDOUT和STDERR进行重定向

$ cat test13b.sh
#!/bin/bash 
# Test using at command 
# 
echo "This script ran at $(date +%B%d,%T)" > test13b.out 
echo >> test13b.out 
sleep 5 
echo "This is the script's end..." >> test13b.out 
# 
$ 
$ at -M -f test13b.sh now
job 8 at 2015-07-14 12:48 
$ 
$ cat test13b.out
This script ran at July14,12:48:18 
This is the script's end... 
$
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值