shell之常用编程语法

1.shell编程规范

1)shell文件行业规范默认后缀为.sh
2)shell首行为#!/bin/bash,注意/bin/bash为当前脚本解释器,可以不写但不能写错了。
3)#表示注释
4)shell对大小写敏感,变量尽量全大写,小写会被鄙视

2.变量

2.1环境变量

全局生效
通过set命令查看
用户环境变量,当前用户生效
系统环境变量,所有用户生效
通过export声明变量

2.2位置变量

将脚本的参数传给脚本,多个参数使用空格隔开

$0:脚本文件名称
$1、$2....$9 :执行脚本的参数
#用例 
[root@hadoop001 wsktest]# cat shellTest.sh 
#!/bin/bash

echo "$0"
echo "$2"
echo "$3"
echo "$1"
[root@hadoop001 wsktest]# sh shellTest.sh start
shellTest.sh


start

2.3预定义变量

  • 由系统保留和维护的一组特殊变量
$0:代表当前脚本的名称
$!:后台运行的最后一个进程的PID
$?:上一个命令退出的状态(0:成功,非0:失败)
$*:当前shell参数集合(整体)
$$:表示当前进程ID号码
$#:代表当前shell的参数个数
$@:当前shell参数集合(逐个读取)
  • $? 上一个命令退出的状态(0:成功,非0:失败)
[root@hadoop001 wsktest]# ll
total 4
-rw-r--r--. 1 root root 55 Apr  9 17:15 shellTest.sh
[root@hadoop001 wsktest]# echo $?
0
[root@hadoop001 wsktest]# lll
-bash: lll: command not found
[root@hadoop001 wsktest]# echo $?
127
  • $# 代表当前shell的参数个数
[root@hadoop001 wsktest]# cat shellTest.sh 
#!/bin/bash
echo "$#"
[root@hadoop001 wsktest]# sh shellTest.sh start stop restart
3
[root@hadoop001 wsktest]# 
  • $* 当前shell参数集合(整体)
[root@hadoop001 wsktest]# cat shellTest.sh 
#!/bin/bash
echo "$*"
[root@hadoop001 wsktest]# sh shellTest.sh start stop restart
start stop restart
  • @ s h e l l ( ) , @ 表当前shell参数集合(逐个读取),不加引号和 *一样,加了则在表示内一个参数
[root@hadoop001 wsktest]# cat shellTest.sh 
#!/bin/bash
test(){
echo "未添加引号"
echo $*
echo $@
echo "添加了引号"
for N in "$*"
do
echo $N
done
echo "====================="
for N in "$@"
do
echo $N
done
}
test 1 2 3 4 5 6
[root@hadoop001 wsktest]# sh shellTest.sh 
未添加引号
1 2 3 4 5 6
1 2 3 4 5 6
添加了引号
1 2 3 4 5 6
=====================
1
2
3
4
5
6
[root@hadoop001 wsktest]# 
  • $$:表示当前进程ID号码
[root@hadoop001 wsktest]# cat wskshell2.sh 
#!/bin/bash
echo $$
[root@hadoop001 wsktest]# sh wskshell2.sh 
30772
[root@hadoop001 wsktest]# sh wskshell2.sh 
30773
[root@hadoop001 wsktest]# sh wskshell2.sh 
30774
  • 注意
1)shell文件默认是无执行权限,编辑完成可添加执行权限:chmod +x shellFile,或 sh shellFile 或 bash shellFile 或 source shellFile 或. shellFile来执行脚本

2.4自定义变量

  • 语法格式
变量名=变量值
注意:
1、等号两边不能有空格
2、变量名大小写敏感,官方建议大写
变量取值:$变量名 或${变量名}
  • 用例
[root@hadoop001 wsktest]# storn=3
[root@hadoop001 wsktest]# echo ${storn}
3

3.算术运算

  • 常用运算符
运算符:+ - * / % 
  • 语法
$((expression)) 或
$[expression] 或
expr expression
  • 用例
[root@hadoop001 wsktest]# echo $((5+4))
9
[root@hadoop001 wsktest]# echo $[5+4]
9
[root@hadoop001 wsktest]# expr 5+4
expr 5+4
[root@hadoop001 wsktest]# expr 5 + 4
9
注意:expr运算的变量间有无空格差别很大

4.内置测试判断

  • 语法
test 测试表达式     或
[ 测试表达式 ]
  • 用例
[root@hadoop001 wsktest]# [ $a -lt $b ]
[root@hadoop001 wsktest]# echo $?
1
[root@hadoop001 wsktest]# [ $a -ge $b ]
[root@hadoop001 wsktest]# echo $?
0
  • 注意
1、测试表达式与[]之前必须有空格

5.数值比较

  • 语法
-eq 等于,equal
-ne 不等于,not equal
-gt 大于,greate than
-ge 大于等于,greate than or equal
-lt 小于,less than
-le 小于等于,less than or equal
  • 用列
[root@hadoop001 wsktest]# [ $a -lt $b ]
[root@hadoop001 wsktest]# echo $?
1
[root@hadoop001 wsktest]# [ $a -ge $b ]
[root@hadoop001 wsktest]# echo $?
0

6、字符串比较

  • 语法
=  等于
!= 不等于
-z 长度为零,如:  [ -z "$myvar" ] 
-n 度为零,如:  [ -z "$myvar" ] 
  • 用例
[root@hadoop001 ~]# a="he"
[root@hadoop001 ~]# b="ha"
[root@hadoop001 ~]# c="he"
[root@hadoop001 ~]# [ a = b ] ;echo $?
1
[root@hadoop001 ~]# [ a = c ] ;echo $?
1
[root@hadoop001 ~]# [ $a = $b ] ;echo $?
1
[root@hadoop001 ~]# [ $a = $c ] ;echo $?
0
[root@hadoop001 ~]# [ $a == $c ] ;echo $?
0
[root@hadoop001 ~]# [ $a == $b ] ;echo $?
1
[root@hadoop001 ~]# [ "$a" == "$b" ];echo $?
1
[root@hadoop001 ~]# [ "$a" == "$c" ];echo $?
0
[root@hadoop001 wsktest]# [ -z "$a" ]
[root@hadoop001 wsktest]# echo $?
1
[root@hadoop001 wsktest]# [ -z "" ]
[root@hadoop001 wsktest]# echo $?
0
  • 注意
1、字符串比较时可以用=也可以用==,左右离比较符必须有空格
2、等于“=”不仅可以用来比较字符串也可以比较数字,注意要有空格,否则就是赋值了。

7.文件判断

  • 语法
-e 文件名,文件存在为真
-r 文件名,文件存在且可读为真
-w 文件名,文件存在且可写为真
-x 文件名,文件存在且可执行为真
-s 文件名,文件存在且有一个字符为真
-d 文件名,文件存在且为目录为真,目录ll显示为d
-f 文件名,文件存在且为普通文件为真,普通文件类型为-
-c 文件名,文件存在且为字符串型特殊文件为真,几乎不用使用到。ll /dev/ 可查看c类型文件
-b 文件名,文件存在且为块特殊文件为真,几乎不会使用到。ll /dev/ 可查看b类型文件
  • 用例
[root@hadoop001 wsktest]# [ -f shellTest.sh ]
[root@hadoop001 wsktest]# echo $?
0
[root@hadoop001 wsktest]# [ -d shellTest.sh ]
[root@hadoop001 wsktest]# echo $?
1

8.逻辑运算符

  • 常用逻辑运算符
代表命令行之间的关系
&&:命令与,
||:命令或
; :命令先后关系
-a:逻辑与
-o:逻辑或
! :逻辑非
  • &&:命令与,cmd1 && cmd2 ,第一个命令成功后执行第二个命令
[root@hadoop001 wsktest]# cat wskshell2.sh 
#!/bin/bash
echo $$
[root@hadoop001 wsktest]# ll /pwd/ssssss && sh wskshell2.sh 
ls: cannot access /pwd/ssssss: No such file or directory
[root@hadoop001 wsktest]# ll /etc/passwd && sh wskshell2.sh 
-rw-r--r--. 1 root root 1664 Apr  7 11:32 /etc/passwd
33536
  • ||:命令或,cmd1 || cmd2 ,第一个命令失败后执行第二个命令
[root@hadoop001 wsktest]# ll /pwd/ssssss ||  sh wskshell2.sh 
ls: cannot access /pwd/ssssss: No such file or directory
33551
[root@hadoop001 wsktest]# ll /etc/passwd || sh wskshell2.sh 
-rw-r--r--. 1 root root 1664 Apr  7 11:32 /etc/passwd
[root@hadoop001 wsktest]# 
  • ; :命令顺序关系,cmd1 ;cmd2;cmd3,仅仅表示先后顺序
[root@hadoop001 wsktest]# ll /etc/passwd ; sh wskshell2.sh 
-rw-r--r--. 1 root root 1664 Apr  7 11:32 /etc/passwd
33566
[root@hadoop001 wsktest]# ll /pwd/ssssss ;  sh wskshell2.sh 
ls: cannot access /pwd/ssssss: No such file or directory
33568
  • -a:逻辑与,cmd1 -a cmd2,cmd1和cmd2都为真时才为真
[root@hadoop001 ~]# ll /root/wsktest/
total 8
-rw-r--r--. 1 root root 182 Apr  9 19:07 shellTest.sh
-rw-r--r--. 1 root root  21 Apr  9 19:10 wskshell2.sh
[root@hadoop001 ~]# [ -e /root/wsktest2 -a  2 -eq 2 ];echo $?
1
[root@hadoop001 ~]# [ -e /root/wsktest -a  2 -eq 2 ];echo $?
0
  • -o:逻辑或,cmd1 -a cmd2,cmd1和cmd2都为假时才为假
[root@hadoop001 ~]# [ -e /root/wsktest2 -o 2 -eq 2 ];echo $?
0
[root@hadoop001 ~]# [ -e /root/wsktest2 -o 2 -eq 3 ];echo $?
1
  • ! :逻辑非,! cmd,注意在[]里面
[root@hadoop001 ~]# [ ! -e /root/wsktest ];echo $?
1
[root@hadoop001 ~]# [  -e /root/wsktest ];echo $?
0

9.date时间获取

  • date 获取以及零时修改当前时间
[root@hadoop001 ~]# date
Wed Apr 10 02:20:57 CST 2019
[root@hadoop001 ~]# date -s "2019-04-10 02:20:57"
Wed Apr 10 02:20:57 CST 2019
[root@hadoop001 ~]# date -s "2019-04-10 13:54:00"
Wed Apr 10 13:54:00 CST 2019
  • 命令帮助查看
[hadoop@hadoop001 ~]$man date
[hadoop@hadoop001 ~]$man help
  • 时间格式化输出
[hadoop@hadoop001 ~]$ date
Wed Apr 10 14:32:36 CST 2019
[hadoop@hadoop001 ~]$ date '+%Y%m%d%H%M%S'
20190410143424
[hadoop@hadoop001 ~]$ date "+%Y%m%d%H%M%S"
20190410143446
  • 用例
#创建当前时间戳.log文件
[root@hadoop001 wsktest]# cat wskshell4.sh 
#!/bin/bash
touch $(date "+%Y%m%d%H%M%S").log
[root@hadoop001 wsktest]# sh wskshell4.sh 
[root@hadoop001 wsktest]# ll
total 16
-rw-r--r--. 1 root root   0 Apr 10 14:41 20190410144112.log
-rw-r--r--. 1 root root 182 Apr  9 19:07 shellTest.sh

10.字符串操作

  • 字符串截取
[hadoop@hadoop001 ~]$ a="123456"
[hadoop@hadoop001 ~]$ echo ${a:2:3}
345
  • 取前缀
[hadoop@hadoop001 ~]$ a="123.log"
[hadoop@hadoop001 ~]$ echo ${a%.*}
123

11.数组

  • 结构
变量名=(元素1 元素2 元素3 元素4 元素5 元素6 )
#注意 默认元素间是以空格分隔
  • 用列
#用列1,元素间使用空格分隔,循环数组
[root@hadoop001 wsktest]# cat array.sh 
#!/bin/bash
arr=(ruoze jepson xingxing wsk shiqi)
for i in ${arr[@]}
do
	echo $i
done
[root@hadoop001 wsktest]# sh array.sh 
ruoze
jepson
xingxing
wsk
shiqi
#用列2,字符串间使用逗分隔,OLD_IFS,IFS这些事固定写法,分隔字符串。
[root@hadoop001 wsktest]# cat array.sh 
#!/bin/bash
S="ruoze,jepson,xingxing,wsk,shiqi"
OLD_IFS="$IFS"
IFS=","
arr=($S)
IFS="OLD_IFS"
for i in ${arr[@]}
do
	echo $i
done
[root@hadoop001 wsktest]# sh array.sh 
ruoze
jepson
xingxing
wsk
shiqi

12.控制语句

12.1 for循环

  • 语法
#语法1:
for 变量 in 集合
do
逻辑
done
#语法2
for((初始变脸;结束循环调节;变量))
do
逻辑
done
  • 用例
#用例1
[root@hadoop001 wsktest]# cat wskshell5.sh 
#!/bin/bash
for i in tony jet bob
do
echo $i
echo "hello $i"
done
[root@hadoop001 wsktest]# sh wskshell5.sh 
tony
hello tony
jet
hello jet
bob
hello bob
#用例2,注意{1..10}可以用`seq 10`取代
[root@hadoop001 wsktest]# cat wskshell6.sh 
#!/bin/bash
for i in {1..10}
do
mkdir dir$i
done
[root@hadoop001 wsktest]# sh wskshell6.sh 
[root@hadoop001 wsktest]# ll
total 64
-rw-r--r--. 1 root root    0 Apr 10 14:41 20190410144112.log
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir1
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir10
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir2
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir3
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir4
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir5
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir6
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir7
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir8
drwxr-xr-x. 2 root root 4096 Apr 10 15:50 dir9
#用例3
[root@hadoop001 wsktest]# cat wskshell7.sh 
#!/bin/bash
for((i=1;i<10;i++))
do
sum=$((sum+$i))
done
echo $sum
[root@hadoop001 wsktest]# sh wskshell7.sh 
45

12.2while循环

  • 语法
#语法1
while [条件]
do
逻辑
done
#语法2
while read -r line
do
逻辑
done
  • 用例
用例1,注意 变量=变量值 ,若写成$变量=变量值就错了,$变量就是变量值的意思
[root@hadoop001 wsktest]# cat wskshell8.sh 
#!/bin/bash
i=0
sum=0
while [ $i -lt 10 ]
do
sum=$(($sum+$i))
i=$[$i+1]
done
echo $sum
#用例2,读取文件的每一行
[root@hadoop001 wsktest]# cat wskshell9.sh 
#!/bin/bash
while read -r line
do
echo $line
done <shellTest.sh
[root@hadoop001 wsktest]# sh wskshell9.sh 
#!/bin/bash
test(){
echo "未添加引号"
echo $*
echo $@
echo "添加了引号"
for N in $*
do
echo $N
done
echo "----------------"
for N in $@
do
echo $N
done
}
test 1 2 3 4 5 6
#用例4,读取文件的每一行,并取第一列和hello拼接
[root@hadoop001 wsktest]# cat wskshell10.sh 
#!/bin/bash
while read -r line
do
echo `echo $line | awk -F: '{print $1}'`:hello 
done < /etc/passwd
[root@hadoop001 wsktest]# sh wskshell10.sh 
root:hello
bin:hello
daemon:hello
adm:hello
lp:hello
sync:hello
shutdown:hello

12.3 if条件判断

  • 语法
#语法1
if 条件
then
   逻辑
fi
#语法2
if 条件
then
   逻辑
else
   逻辑
fi
#语法3
if 条件
then
	逻辑
elif
then
	逻辑
else
	逻辑
fi	
  • 用例
# 用列1
[root@hadoop001 wsktest]# cat wskshell11.sh 
#!/bin/bash
if [ 2 -eq 2 ]
then
echo yes
else
echo no
fi
[root@hadoop001 wsktest]# sh wskshell11.sh 
yes
#用列2
[root@hadoop001 wsktest]# sh wskshell20.sh -1
参数小于0
[root@hadoop001 wsktest]# sh wskshell20.sh 5
参数小于10
[root@hadoop001 wsktest]# sh wskshell20.sh 15
参数小于20
[root@hadoop001 wsktest]# sh wskshell20.sh 24
参数大于等于20

12.4 case 条件选择

  • 语法
语法1:
case $变量名称 in
条件1)
	命令序列
	;;
条件2)
	命令序列
	;;
条件3)
	命令序列
	;;
*)
esac
语法2:
case $变量名称 in
条件1|条件2)
	命令序列
	;;
条件3|条件4)
	命令序列
	;;
条件5|条件6)
	命令序列
	;;
*)
esac
  • 用例
[root@hadoop001 wsktest]# cat wskshell12.sh 
#!/bin/bash
case $1 in
1)
	echo "我是"$1
	;;
2)
        echo "我是"$1
        ;;
3)
        echo "我是"$1
        ;;
*)
        echo "我是"$1
        ;;
esac	
[root@hadoop001 wsktest]# sh wskshell12.sh 2
我是2

13.函数

  • 语法
语法1:
name(){
	命令序列
}
语法2:
function name{
	命令序列
}
  • 用例
[root@hadoop001 wsktest]# cat wskshell13.sh 
#!/bin/bash
sum(){
	echo $(($1+$2))
}
sum 2 5
[root@hadoop001 wsktest]# sh wskshell13.sh 
7
  • 注意
1)shell是顺序执行的,故函数体要写在函数调用前
2)函数的参数的传递通过$1..9

14.awk文本扫描处理

  • 语法
awk '{pattern + action}' {filenames}
  • 用列
[root@hadoop001 wsktest]# cat test.log 
a,1,你
b,2,们
c,3,好
d,4,啊
e,5,我
#输出第一行,NR表示行号
[root@hadoop001 wsktest]# cat test.log| awk -F "," 'NR==1' 
a,1,你
#输出第一行之后的所有行
[root@hadoop001 wsktest]# cat test.log| awk -F "," 'NR>1' 
b,2,们
c,3,好
d,4,啊
e,5,我
#输出第一列和第二列
[root@hadoop001 wsktest]# awk -F "," '{print $1,$2}' test.log 
a 1
b 2
c 3
d 4
e 5
#输出第2列第二行
[root@hadoop001 wsktest]# awk -F "," 'NR==2{print $2}' test.log 
2

15.sed流编辑器

  • 语法
sed [options] 'command' file(s)
  • 用列
#将文件里的每行首个a使用aa替换
[root@hadoop001 wsktest]# cat sed.log 
a ser swef
123 43 45 
44 5 a 1333
hello
[root@hadoop001 wsktest]# sed -i 's/a/aa/' sed.log 
[root@hadoop001 wsktest]# cat sed.log 
aa ser swef
123 43 45 
44 5 aa 1333
hello
#将文件中的每行首个aa使用b'替换
[root@hadoop001 wsktest]# cat sed.log 
aa ser swef
123 43 45 
44 5 aa 1333
hello
[root@hadoop001 wsktest]# sed -i "s/aa/b'/" sed.log 
[root@hadoop001 wsktest]# cat sed.log 
b' ser swef
123 43 45 
44 5 b' 1333
hello
#将文件中的s使用ll全局替换
[root@hadoop001 wsktest]# cat sed.log 
sss ser swef
123 43 45 
44 5 sss 1333
hello
[root@hadoop001 wsktest]# sed -i "s/s/ll/g" sed.log 
[root@hadoop001 wsktest]# cat sed.log 
llllll ller llwef
123 43 45 
44 5 llllll 1333
hello
#将文件的每行首添加指定字符串
[root@hadoop001 wsktest]# cat sed.log 
llllll ller llwef
123 43 45 
44 5 llllll 1333
hello
[root@hadoop001 wsktest]# sed -i 's/^/uu&/g' sed.log 
[root@hadoop001 wsktest]# cat sed.log 
uullllll ller llwef
uu123 43 45 
uu44 5 llllll 1333
uuhello
#将文件的每行尾添加指定字符串
[root@hadoop001 wsktest]# sed -i 's/$/&wwk/g' sed.log 
[root@hadoop001 wsktest]# cat sed.log 
uullllll ller llwefwwk
uu123 43 45 wwk
uu44 5 llllll 1333wwk
uuhellowwk

16.计划任务

16.1一次性计划任务:at

#生产不常用
#at 时间,设置一次性定时任务启动时间,并进入编辑模式
#ctr+d表示保存退出
#at -l 列出未执行的计划任务
[root@hadoop001 wsktest]# date
Thu Apr 11 02:08:47 CST 2019
[root@hadoop001 wsktest]# at 02:10
at> cp /etc/passwd /root/wsktest/
at> <EOT>
job 4 at 2019-04-11 02:10
[root@hadoop001 wsktest]# ll /root/wsktest/
total 64
-rw-r--r--. 1 root root    0 Apr 10 14:41 20190410144112.log
-rw-r--r--. 1 root root 1664 Apr 11 02:10 passwd

16.2 周期性计划任务:crontab

  • 语法
#生产用的最多
# 确保服务是启动,service crond status
# 确保服务是开机自启动的,chkconfig crond --list;确保在系统对应的启动级别上(主要是3和5)该服务是on的,即开机自启动
# crontal -l 列出所有的计划任务
# crontab -e 进入计划任务编辑,注意* * * * * ,代表每分、时、日、月、周
  • 用列
#上方的计划任务表示每周3的夜里两点执行 任务
[root@hadoop001 wsktest]# crontab -l
0 2 * * 3 cp /etc/passwd /tmp
#每隔半个月清空/tmp临时文件
[root@hadoop001 wsktest]# crontab -l
0 1 10,25 * * rm -rf /tmp/*
#每隔10小时进行时间同步
[root@hadoop001 wsktest]# crontab -l
0 */10 * * * 	ntpdate 0.asia.pool.ntp.org
#每天夜里1,2,3,4,5,6点执行时钟同步
[root@hadoop001 wsktest]# crontab -l
0 1-6 * * * 	ntpdate 0.asia.pool.ntp.org

扩展1:/etc/init.d/目录下都是系统启动脚本,可供借鉴学习

扩展2:cat /etc/shells ,可查询系统的shell环境有哪些

扩展3:shell中单引号(’’)与双引号("")都是用来表示字符串,唯一区别时双引号会解释字符串中的特殊字符($,,`)而单引号不会;\ 表示命令换行

扩展4:反引号括起来的是一行命令,是用于将一个命令的标准输出插在一个命令行中任何位置等价于$(cmd),kill -9 $(pgrep xx),查询某进程并杀死。

猜你喜欢

转载自blog.csdn.net/qq_32641659/article/details/89223802