shell之常用编程语法

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 scripts]# cat shellTest.sh 
#!/bin/bash
echo "$0"
echo "$1"
echo "$2"
echo "$3"
[root@hadoop001 scripts]# sh shellTest.sh start a b 
shellTest.sh
start
a
b

2.3预定义变量

由系统保留和维护的一组特殊变量

$0:代表当前脚本的名称
$!:后台运行的最后一个进程的PID
$?:上一个命令退出的状态(0:成功,非0:失败)
$*:当前shell参数集合(整体)
$$:表示当前进程ID号码
$#:代表当前shell的参数个数
$@:当前shell参数集合(逐个读取)

$? 上一个命令退出的状态(0:成功,非0:失败)

[root@hadoop001 scripts]# ll
total 584508
-rw-r--r--. 1 root root 598528000 Jan  1 06:01 mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar
drwxr-xr-x. 2 root root      4096 Apr 14 09:15 mysqlrpm
-rw-r--r--. 1 root root        53 Apr 15 10:55 shellTest.sh
[root@hadoop001 scripts]# echo $?
0
[root@hadoop001 scripts]# lll
-bash: lll: command not found
[root@hadoop001 scripts]# echo $?
127

$# 代表当前shell的参数个数

[root@hadoop001 scripts]# cat shellTest.sh 
#!/bin/bash

echo "$#"
[root@hadoop001 scripts]# sh shellTest.sh first second third
3

$* 当前shell参数集合(整体)

[root@hadoop001 scripts]# cat shellTest.sh 
#!/bin/bash

echo "$*"
[root@hadoop001 scripts]# sh shellTest.sh first second third
first second third

@表当前shell参数集合(逐个读取),不加引号和*一样,加了则在表示内一个参数

[root@hadoop001 scripts]# 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 scripts]# 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

$$:表示当前进程ID号

[root@hadoop001 scripts]# cat shellTest2.sh 
#!/bin/bash
echo $$
[root@hadoop001 scripts]# sh shellTest2.sh 
3274
[root@hadoop001 scripts]# sh shellTest2.sh 
3275
[root@hadoop001 scripts]# sh shellTest2.sh 
3276

shell文件默认是无执行权限,编辑完成可添加执行权限:chmod +x shellFile,或 sh shellFile 或 bash shellFile 或 source shellFile 或. shellFile来执行脚本

2.4自定义变量

1.语法格式:变量名=变量值
2.注意:
1、等号两边不能有空格
2、变量名大小写敏感,官方建议大写,变量取值: 变 量 名 或 变量名 或 {变量名}

3.用例:

[root@hadoop001 scripts]# param=3
[root@hadoop001 scripts]# echo ${param}
3

3.算术运算

3.1常用运算符

运算符:+ - * / %

语法:

( ( e x p r e s s i o n ) ) 或 ((expression)) 或 ((expression))[expression] 或expr expression

用例:

[root@hadoop001 scripts]# echo $((5+5))
10
[root@hadoop001 scripts]# echo $[5+5]
10
[root@hadoop001 scripts]# expr 5+5
5+5
[root@hadoop001 scripts]# expr 5 + 5
10

*注意:expr运算的变量间有无空格差别很大

4.内置测试判断

语法:

test 测试表达式 或 [ 测试表达式 ]

用例:

[root@hadoop001 scripts]# a=2
[root@hadoop001 scripts]# b=3
[root@hadoop001 scripts]# [ $a -lt $b ]
[root@hadoop001 scripts]# echo $?
0
[root@hadoop001 scripts]# [ $a -ge $b ]
[root@hadoop001 scripts]# echo $?
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 scripts]# a=2
[root@hadoop001 scripts]# b=3
[root@hadoop001 scripts]# [ $a -lt $b ]
[root@hadoop001 scripts]# echo $?
0
[root@hadoop001 scripts]# [ $a -ge $b ]
[root@hadoop001 scripts]# echo $?
1

6.字符串比较

语法:

= 等于
!= 不等于
-z 长度为零,如: [ -z “ m y v a r " ] − n 度 为 零 , 如 : [ − n " myvar" ] -n 度为零,如: [ -n " myvar"]n[n"myvar” ]

用例:

[root@hadoop001 scripts]# a="aa"
[root@hadoop001 scripts]# b="ab"
[root@hadoop001 scripts]# c="aa" 
[root@hadoop001 scripts]# [ a = b ] ; echo $?  
1
[root@hadoop001 scripts]# [ a = c ] ; echo $?  
1
[root@hadoop001 scripts]# [ $a = $b ] ; echo $?
1
[root@hadoop001 scripts]# [ $a = $c ] ; echo $? 
0
[root@hadoop001 scripts]# [ "$a" = "$b" ] ; echo $?   
1
[root@hadoop001 scripts]# [ "$a" = "$c" ] ; echo $? 
0
[root@hadoop001 scripts]# [ -z "$a" ]
[root@hadoop001 scripts]# echo $?
1
[root@hadoop001 scripts]# [ -z "" ] ; echo $?
0

注意:

1、字符串比较时可以用=也可以用==,左右离比较符必须有空格
2、等于“=”不仅可以用来比较字符串也可以比较数字,注意要有空格,否则就是赋值了。

7.文件判断

语法:

-e 文件名,文件存在为真
-r 文件名,文件存在且可读为真
-w 文件名,文件存在且可写为真
-x 文件名,文件存在且可执行为真
-s 文件名,文件存在且有一个字符为真
-d 文件名,文件存在且为目录为真,目录ll显示为d
-f 文件名,文件存在且为普通文件为真,普通文件类型为-
-c 文件名,文件存在且为字符串型特殊文件为真,几乎不用使用到。ll /dev/ 可查看c类型文件

用例:

[root@hadoop001 scripts]# [ -f shellTest.sh ] ; echo $?
0
[root@hadoop001 scripts]# [ -d shellTest.sh ] ; echo $? 
1

8.逻辑运算符

常用逻辑运算符:

代表命令行之间的关系
&&:命令与,
||:命令或
; :命令先后关系
-a:逻辑与
-o:逻辑或
! :逻辑非

&&:命令与,cmd1 && cmd2 ,第一个命令成功后执行第二个命令

[root@hadoop001 scripts]# ll /opt/scripts/ && sh shellTest2.sh 
total 584512
-rw-r--r--. 1 root root 598528000 Jan  1 06:01 mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar
drwxr-xr-x. 2 root root      4096 Apr 14 09:15 mysqlrpm
-rw-r--r--. 1 root root        20 Apr 15 11:08 shellTest2.sh
-rw-r--r--. 1 root root       186 Apr 15 11:05 shellTest.sh
3312
[root@hadoop001 scripts]# ll /opt/script/ && sh shellTest2.sh  
ls: cannot access /opt/script/: No such file or directory

||:命令或,cmd1 || cmd2 ,第一个命令失败后执行第二个命令,不失败不执行

[root@hadoop001 scripts]# ll /opt/script/ || sh shellTest2.sh   
ls: cannot access /opt/script/: No such file or directory
3315
[root@hadoop001 scripts]# ll /opt/scripts/ || sh shellTest2.sh   
total 584512
-rw-r--r--. 1 root root 598528000 Jan  1 06:01 mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar
drwxr-xr-x. 2 root root      4096 Apr 14 09:15 mysqlrpm
-rw-r--r--. 1 root root        20 Apr 15 11:08 shellTest2.sh
-rw-r--r--. 1 root root       186 Apr 15 11:05 shellTest.sh

; :命令顺序关系,cmd1 ;cmd2;cmd3,仅仅表示先后顺序

[root@hadoop001 scripts]# ll /opt/scripts/ ; sh shellTest2.sh   
total 584512
-rw-r--r--. 1 root root 598528000 Jan  1 06:01 mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar
drwxr-xr-x. 2 root root      4096 Apr 14 09:15 mysqlrpm
-rw-r--r--. 1 root root        20 Apr 15 11:08 shellTest2.sh
-rw-r--r--. 1 root root       186 Apr 15 11:05 shellTest.sh
3318
[root@hadoop001 scripts]# ll /opt/script/ ; sh shellTest2.sh  
ls: cannot access /opt/script/: No such file or directory
3320

-a:逻辑与,cmd1 -a cmd2,cmd1和cmd2都为真时才为真

[root@hadoop001 scripts]# [ -e /opt/scripts/ -a 2 -eq 2 ];echo $?
0
[root@hadoop001 scripts]# [ -e /opt/script/ -a 2 -eq 2 ];echo $? 
1

-o:逻辑或,cmd1 -o cmd2,cmd1和cmd2都为假时才为假

[root@hadoop001 scripts]# [ -e /opt/scripts/ -o 2 -eq 2 ];echo $? 
0
[root@hadoop001 scripts]# [ -e /opt/script/ -o 2 -eq 3 ];echo $?  
1

! :逻辑非,! cmd,注意在[]里面

[root@hadoop001 scripts]# [ -e /opt/scripts/ ];echo $?
0
[root@hadoop001 scripts]# [ ! -e /opt/scripts/ ];echo $?
1

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"

命令帮助查看:

[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

用例:

[root@hadoop001 scripts]# sh shellTest3.sh 
[root@hadoop001 scripts]# ll
total 584516
-rw-r--r--. 1 root root         0 Apr 15 11:40 20190415114052.log
-rw-r--r--. 1 root root 598528000 Jan  1 06:01 mysql-5.7.23-1.el7.x86_64.rpm-bundle.tar
drwxr-xr-x. 2 root root      4096 Apr 14 09:15 mysqlrpm
-rw-r--r--. 1 root root        20 Apr 15 11:08 shellTest2.sh
-rw-r--r--. 1 root root        47 Apr 15 11:40 shellTest3.sh
-rw-r--r--. 1 root root       186 Apr 15 11:05 shellTest.sh
[root@hadoop001 scripts]# cat shellTest3.sh 
#!/bin/bash
touch $(date "+%Y%m%d%H%M%S").log

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

用例:

[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.计划任务

周期性计划任务: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

17.拓展

1:/etc/init.d/目录下都是系统启动脚本

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

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

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

你可能感兴趣的:(hadoop)