Shell编程

发布于 2021-02-05  130 次阅读


Hello World

#!/bin/bash
# #!告诉系统用哪一种shell执行
echo "Hello World !"

Shell变量

定义变量

变量名和等号之间不能有空格

name="7e2hj"
readonly name #设置name为只读变量

使用变量

echo ${name}

Shell字符串

单引号

str='this is a string'

单引号里的任何字符都会原样输出

单引号字符串中的变量是无效

双引号

name='7e2hj'
str="Hello, \"$name\"!"
echo $str

输出结果为:

Hello, "7e2hj"!

双引号里可以有变量转义字符

获取字符串长度

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

截取字符串

string="abcdefg"
#从第2个字符开始截取4 个字符
echo ${string:1:4} # 输出 bcde

注意:第一个字符的索引值为 0

字符串替换

#用string来替换parameter变量中所有匹配的pattern
${parameter//pattern/string} 

Shell数组

bash只支持一维数组

定义数组

array_name=(value0 value1 value2)
#单独定义
#可以不使用连续的下标,且下标的范围没有限制
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen

读取数组

valuen=${array_name[n]}
#使用 @ 符号可以获取数组中的所有元素
echo ${array_name[@]}

获取数组长度

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

Shell注释

# 单行注释

#多行注释
# [!] 也可以用别的符号代替
:<<!
注释内容
注释内容
!

Shell传参

shell用$n(n表示一个数字)来接收外部传参

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

特殊参数

参数处理 说明
$# 传递到脚本的参数个数
$? 显示最后一条命令的退出状态。0表示没有错误,其他值表明有错误。
$* 以一个单字符串显示所有向脚本传递的参数。
$@ 与$*类似,但不是一个字符串,在引号中返回每个参数。
$$ 脚本运行的当前进程ID号
$! 后台运行的最后一个进程的ID号
$- 显示Shell使用的当前选项,与set命令功能相同。

注意:$* 与 $@ 区别:

#!/bin/bash
echo "-- \$* 演示 ---"
for i in "$*"; do
    echo $i
done

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

执行脚本,输出结果如下所示:

$ chmod +x test.sh 
$ ./test.sh 1 2 3
-- $* 演示 ---
1 2 3
-- $@ 演示 ---
1
2
3

Shell运算

原生bash不支持简单的数学运算,但可以通过 expr 命令实现

#!/bin/bash
val=`expr 2 + 2`
#val=`expr 2 \* 2`
echo "两数之和为 : $val"

注意:

  • 使用的是反引号[`]而不是单引号[']
  • 表达式和运算符之间要有空格,例如 2+2 必须写成 2 + 2
  • 乘号前必须加反斜杠\
  • 使用$((表达式))也可以实现计算,此处表达式中的 * 不需要转义符号 \

关系运算符

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

运算符 说明 举例
== 检测两个数是否相等,相等返回 true。 [ $a == $b ]
!= 检测两个数是否不相等,不相等返回 true。 [ $a != $b ]
-eq ==,EQUAL [ $a -eq $b ]
-ne !=,NOT EQUAL [ $a -ne $b ]
-gt >,GREATER THAN [ $a -gt $b ]
-lt <,LESS THAN [ $a -lt $b ]
-ge >=,GREATER THAN OR EQUAL [ $a -ge $b ]
-le <=,LESS THAN OR EQUAL [ $a -le $b ]

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

字符串运算符

运算符 说明 举例
= 检测两个字符串是否相等,相等返回 true。 [ $a = $b ]
!= 检测两个字符串是否不相等,不相等返回 true。 [ $a != $b ]
-z 检测字符串长度是否为0,为0返回 true。 [ -z $a ]
-n 检测字符串长度是否不为 0,不为 0 返回 true。 [ -n "$a" ]
$ 检测字符串是否为空,不为空返回 true。 [ $a ]

注意:

  • 使用 -n 时 $a 必须加上双引号
  • 使用>,<比较字符串时需要使用[[]]或者[\>]

逻辑运算符

运算符 说明 举例
&& 逻辑的 AND [[ $a -lt 100 && $b -gt 100 ]]
|| 逻辑的 OR [[ $a -lt 100 || $b -gt 100 ]]

注意:使用双[][[]]而不是单[]

文件测试运算符

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

操作符 说明 举例
-e file 检测文件(包括目录)是否存在 [ -e $file ]
-s file 检测文件是否为空(文件大小是否大于0)
不为空返回 true。
[ -s $file ]
-b file 检测文件是否是块设备文件 [ -b $file ]
-c file 检测文件是否是字符设备文件 [ -c $file ]
-d file 检测文件是否是目录 [ -d $file ]
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件) [ -f $file ]
-g file 检测文件是否设置了 SGID 位 [ -g $file ]
-k file 检测文件是否设置了粘着位(Sticky Bit) [ -k $file ]
-p file 检测文件是否是有名管道 [ -p $file ]
-u file 检测文件是否设置了 SUID 位 [ -u $file ]
-r file 检测文件是否可读 [ -r $file ]
-w file 检测文件是否可写 [ -w $file ]
-x file 检测文件是否可执行 [ -x $file ]

其他检查符:

  • -S: 判断某文件是否 socket。
  • -L: 检测文件是否存在并且是一个符号链接。

read命令

read使用

read 命令接收参数 需要使用空格分隔

read firstStr secondStr
echo "第一个参数:$firstStr 第二个参数:$secondStr"

执行结果:

$ sh test.sh 
1 2 3 4
第一个参数:1 第二个参数:2 3 4

注意:

  • 如果输入的词组个数大于需要的参数个数
  • 则多出的词组将整体被作为最后一个参数

read参数

参数说明:

  • -p 输入提示文字
  • -n 输入字符长度限制(达到6位,自动结束)
  • -t 输入限时
  • -s 隐藏输入内容
read -p "请输入一段文字:" -n 6 -t 5 -s password
echo -e "\npassword is $password"

执行结果:

$ sh test.sh 
请输入一段文字:
password is asdfgh

重定向

重定向命令

文件描述符:

  • 0 是标准输入(STDIN)
  • 1 是标准输出(STDOUT)
  • 2 是标准错误输出(STDERR)
命令 说明
command > file 将输出重定向到 file。
command < file 将输入重定向到 file。
command >> file 将输出以追加的方式重定向到 file。
command n> file 将文件描述符为 n 的文件重定向到 file。
command &> file 将错误和正确输出都重定向到 file。
command > file 2>&1 将错误和正确输出都重定向到 file。
command << tag 从标准输入流读取直到遇到tag。

注意:

  • n> 之间不能有空格
  • 放在>后面的&,表示重定向的目标不是一个文件,而是一个文件描述符
  • 而&>file是一种特殊的用法,也可以写成>&file,二者的意思完全相同

/dev/null 文件

如果不想在屏幕显示输出结果, 可以重定向到 /dev/null

command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃

如果尝试从该文件读取内容,那么什么也读不到

将命令的输出重定向到它,会起到"禁止输出"的效果

流程控制语句

if

if condition1
then
    command1
elif condition2 
then 
    command2
else
    commandN
fi

for

for var in item1 item2 ... itemN
do
    command1
done
for((assignment;condition:next))
do
    command_1
done;

通常情况下 shell 变量调用需要加 $

但是 for 的 (()) 中不需要,下面来看一个例子:

#!/bin/bash
for((i=1;i<=5;i++));do
    echo "这是第 $i 次调用";
done;

while

while condition
do
    command
done

unit

until condition
do
    command
done

case esac

case 值 in
模式1)
    command1
    ;;
模式2)
    command1
    ;;
esac

例:

case $aNum in
    1|2)  echo '你选择了 1|2'
    ;;
    3)  echo '你选择了 3'
    ;;
    *)  echo '你没有输入 1 到 3 之间的数字'
    ;;
esac

函数

定义函数

[ function ] funname [()]
{
    action;
    [return int;]
}

说明:

  • 可以用function fun() 定义,也可以直接fun() 定义
  • 参数返回,使用 return 返回,范围(0~255)
  • 如果没有return,将返回最后一条命令运行结果

调用函数

#!/bin/bash
demoFun(){
    echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"

函数返回值

#!/bin/bash
test(){
    echo $((1+1))
    return $((2+2))
}
a=`test`
echo "$?:$a"

执行结果:

4 2

注意:

  • $? 获取函数返回值
  • $a 获取函数执行的所有输出值
  • echo 同 $a

Shell 文件包含

被包含的文件 test1.sh 不需要可执行权限。

. filename 
或
source filename

注意:点号.和文件名中间有空格