shell编程

shell编程

什么是shell?

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。

Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

变量:

声明变量:export name="value" declare -i ab 声明整数型变量

"":包含的变量会被解释

'':包含的变量会当做字符串解释

``:反引号中的内容会作为系统命令,并执行其内容,可以替换输出一个变量

declare命令用来声明shell变量:

参数说明

  • +/-  "-“可用来指定变量的属性,”+"则是取消变量所设的属性。
  • -f  仅显示函数。
  • r  将变量设置为只读。
  • x  指定的变量会成为环境变量,可供shell以外的程序来使用。
  • i  [设置值]可以是数值,字符串或运算式。
# declare -i ef //声明整数型变量
# ef=1  //变量赋值(整数值)
# echo $ef //显示变量内容
# declare +i ef //取消变量属性
# declare -r ab //设置变量为只读
# unset variable_name //删除变量

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

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

获取字符串的长度

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

Shell 数组

bash支持一维数组(不支持多维数组),并且没有限定数组的大小。

类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。

定义数组

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

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

例如:

array_name=(value0 value1 value2 value3)

或者

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[@]}

获取数组的长度

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

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

多行注释

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

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

EOF 也可以使用其他符号:

:<<'
注释内容...
注释内容...
注释内容...
'

:<<!
注释内容...
注释内容...
注释内容...
!

特殊变量:

$1,$2,…:对应调用第1,第2等参数
$0:命令本身
$*:以一个单字符串显示所有向脚本传递的参数。如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$@:与$*相同,但是使用时加引号,并在引号中返回每个参数。如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。
$#:传递给脚本的参数的个数
$?:显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

$*$@ 区别:

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

基本运算

  • 数学运算
#!/bin/bash
val=`expr 2 + 2`
echo "两数之和为 : $val"

两点注意:

  • 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。
  • 完整的表达式要被反引号 `` 包含
[root@master ~]# echo "today is `date` "
today is 2022年 02月 05日 星期六 12:41:11 CST
  • 判断文件的行数:
[root@master ~]# wc -l mysql.sh 
17 mysql.sh
[root@master ~]# wc -l mysql.sh |cut -d' ' -f1
17
[root@master ~]# cat linecount.sh 
#!/bin/bash
linecount="$(wc -l $1|cut -d' ' -f1)"
echo "This file have ${linecount} lines"
  • 计算/etc/passwd文件中的第10个用户和第20用户的 ID之和:
[root@master ~]# cat /etc/passwd|head -10|tail -1
operator:x:11:0:operator:/root:/sbin/nologin
#用户名:密码占位符:uid:gid:用户描述信息:家目录:登录指定shell
[root@master ~]# cat /etc/passwd|head -10|tail -1|cut -d: -f3
11
[root@master shell]# cat id_sum.sh 
#!/bin/bash
userid1=$(cat /etc/passwd|head -10|tail -1|cut -d: -f3)
userid2=$(cat /etc/passwd|head -10|tail -1|cut -d: -f3)
userid_sum=$[$userid1 + $userid2]
echo $userid_sum

  • 统计文件空行
[root@master shell]# cat blank_count.sh 
#!/bin/bash
blank1=$(grep "^$" $1 | wc -l)
blank2=$(grep "^$" $1 | wc -l)
allblank=$[$blank1 + $blank2]
echo "The sum space line: $allblank"
[root@master shell]# bash blank_count.sh /etc/httpd/conf/httpd.conf.bak ~/mysql.sh 
The sum space line: 74

数值比较

-gt:大于(greater than)

-ge:大于等于

-eq:等于

-ne:不等于

-lt:小于(less than)

-le:小于等于

  • 数字比大小
[root@master shell]# cat diff.sh 
#!/bin/bash
read -p "请输入两个正整数" num1 num2
if [ $num1 -gt $num2 ];then
	echo "$num1 > $num2"
elif [ $num1 -lt $num2 ];then
	echo "$num1 < $num2"
else 
	echo "$num1 = $num2"
fi
[root@master shell]# bash diff.sh 
请输入两个正整数2 4
2 < 4

文件测试

简单的存在性测试:
-e FILE :文件存在性测试,存在为真,否则为假
存在性及类型测试:
-b FLIE:是否存在且为块设备文件;
-c FILE:是否存在且为字符设备文件;
-d FILE:是否存在且为目录文件;
-f FILE:是否存在且为普通文件;
-h FILE 或 -L FILE : 存在且为符号链接文件;
-p FIEL :是否存在且为命名管道文件;
-S FILE:是否存在且为套接文件;
文件权限测试:
-r FILE:是否存在且可读
-w FILE:是否存在且可写
-x FILE:是否存在可执行
文件特殊权限测试:
-g FILE:是否存在且拥有sgid权限;
-u FILE:是否存在且拥有suid权限;
-k FILE:是否存在且拥有sticky权限;
文件大小测试:
-s FILE:是否存在且非空
文件是否打开:
- fd:fd表示文件描述符是否已经打开且与某终端相关
-N FILE:文件自动上一次读取之后是否被修改过;
-O FILE:当前用户是否为文件的属主;
-G FILE:当前有效用户是否为文件数组;
双目测试:
FILE1 -ef FILE2 :FILE1与FILE2是否指向同一个设备上的相同inode
FILE1 -nt FILE2:FILE1是否新于FILE2
FILE1 -ot FILE2:FILE1是否旧于FILE2
file="/var/www/runoob/test.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

组合测试

逻辑运算符:
&&代表的意思是当前一个命令执行成功时会继续执行后续的命令,当前一个命令执行失败的时候不会执行后续的命令
||代表的意思是当前一个命令执行成功时不会继续执行后续的命令,当前一个命令执行失败的时候会执行后续的命令
第一种方式:
COMMAND1 && COMMAND2
COMMAND1 || COMMAND2
! COMMAND
第二种方式:
EXPRESSION1 -a EXPRESSION2
EXPRESSION1 -o EXPRESSION2
! EXPRESSION
Note:必须使用测试命令进行

printf命令

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

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

姓名     性别   体重kg
郭靖     男      66.12
杨过     男      48.65
郭芙     女      47.99

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

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

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

shell流程控制

选择执行

if 判断条件;then
条件为真的分支代码
elif 判断条件;then
条件为真的分支代码
else
条件为假的分支代码
fi
  • 判断用户是否存在,如果不存在就添加用户,并设置密码和用户相同
[root@master shell]# cat user.sh 
#!/bin/bash
if [ $# -lt 1 ];then
	echo "at least one argument"
	exit 1
fi 
if id $1 &> /dev/null;then
	echo "$1 exists"
	exit 0
else
	useradd $1
	[ $? -eq 0 ] && echo "$1"|passwd --stdin $1 &>/dev/null
	echo "user $1 have been created"
fi
  • 判断流程
[root@master shell]# ps -ef |grep -c mysql
1
[root@master shell]# ps -ef|grep mysql
root       2818   1741  0 19:46 pts/1    00:00:00 grep --color=auto mysql
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "false"; fi

for循环

语法:

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

写成一行:

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

  • 循环输出
for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done
输出结果:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
----------------------
#!/bin/bash

for str in This is a string
do
    echo $str
done
输出结果:
This
is
a
string

while语句

语法:

while condition
do
    command
done

实例:

#!/bin/bash
int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done
命令:let

let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上 $ 来表示变量。如果表达式中包含了空格或其他特殊字符,则必须引起来。

while循环可用于读取键盘信息:

echo '按下 <CTRL-D> 退出'
echo -n '输入你最喜欢的语言: '
while read FILM
do
    echo "$FILM 是最好的语言!"
done

无限循环

无限循环语法格式:

while :
do
    command
done

或者

while true
do
    command
done

或者

for (( ; ; ))

until 循环

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

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

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

until 语法格式:

until condition
do
    command
done

condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

以下实例我们使用 until 命令来输出 0 ~ 9 的数字:

#!/bin/bash

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

实例:

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

break命令

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

下面的例子中,脚本进入死循环直至用户输入数字大于5。

#!/bin/bash
while :
do
    echo -n "输入 1 到 5 之间的数字:"
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
            break
        ;;
    esac
done

continue

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

#!/bin/bash
while :
do
    echo -n "输入 1 到 5 之间的数字: "
    read aNum
    case $aNum in
        1|2|3|4|5) echo "你输入的数字为 $aNum!"
        ;;
        *) echo "你输入的数字不是 1 到 5 之间的!"
            continue
            echo "游戏结束"
        ;;
    esac
done

shell函数

demoFun(){
    echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值