概述
shell是一个命令行解释器,它接收应用程序/用户命令,然后操作系统内核。shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强。
shell解析器
[root@iZbp1b61tux603e0rlumg5Z test]# cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin
常用的解析器有sh和bash。其实sh最终调用的也是bash
[root@iZbp1b61tux603e0rlumg5Z bin]# cd /bin/
[root@iZbp1b61tux603e0rlumg5Z bin]# ll | grep bash
-rwxr-xr-x 1 root root 960376 Nov 20 2015 bash
lrwxrwxrwx 1 root root 10 May 3 2016 bashbug -> bashbug-64
-rwxr-xr-x 1 root root 7041 Nov 20 2015 bashbug-64
lrwxrwxrwx 1 root root 4 May 3 2016 sh -> bash
sh软链接到bash。查看系统默认解析器
[root@iZbp1b61tux603e0rlumg5Z bin]# echo $SHELL
/bin/bash
[root@iZbp1b61tux603e0rlumg5Z bin]#
shell脚本
脚本格式
脚本以"#!/bin/bash"开头(指定解析器)
执行脚本用"sh"或者"bash"执行本质是bash解析器帮助执行脚本,所以不需要执行权限。
使用"./"执行脚本是用户自己执行脚本,所以需要脚本的执行权限。
1)在/dev/test文件下创建文件faker.txt,并追加写入"NO.1 LOL"
#!/bin/bash
cd /dev/test/
touch faker.txt
echo "NO.1 LOL" >> faker.txt
shell中的变量
系统变量
1.常用系统变量
$HOME、$PWD、$SHELL、$USER等
2.自定义变量
1)定义变量: 变量=值(等号两边不能有空格)
2)撤销变量:unset 变量
3)声明静态变量:readonly变量,注意:不能unset
[root@iZbp1b61tux603e0rlumg5Z test]# A = 1
-bash: A: command not found
[root@iZbp1b61tux603e0rlumg5Z test]# A=1
[root@iZbp1b61tux603e0rlumg5Z test]# echo $A
1
[root@iZbp1b61tux603e0rlumg5Z test]#
[root@iZbp1b61tux603e0rlumg5Z test]# unset A
[root@iZbp1b61tux603e0rlumg5Z test]# echo $A
[root@iZbp1b61tux603e0rlumg5Z test]#
[root@iZbp1b61tux603e0rlumg5Z test]# readonly B=2
[root@iZbp1b61tux603e0rlumg5Z test]# echo $B
2
[root@iZbp1b61tux603e0rlumg5Z test]# unset B
-bash: unset: B: cannot unset: readonly variable
[root@iZbp1b61tux603e0rlumg5Z test]#
在bash中,默认类型都是字符串类型,无法直接进行数值运算。变量的值如果有空格,需要使用双引号或单引号括起来。
[root@iZbp1b61tux603e0rlumg5Z test]# C=1+1
[root@iZbp1b61tux603e0rlumg5Z test]# echo $C
1+1
[root@iZbp1b61tux603e0rlumg5Z test]#
[root@iZbp1b61tux603e0rlumg5Z test]# D=haha hehe
-bash: hehe: command not found
[root@iZbp1b61tux603e0rlumg5Z test]# D="haha hehe"]
[root@iZbp1b61tux603e0rlumg5Z test]# echo $D
haha hehe]
[root@iZbp1b61tux603e0rlumg5Z test]#
特殊变量
1.$n
n为数字,$0代表该脚本名称,$1-$9代表第一到第九个参数,10个以上的参数需要用大括号包含,如${10}
[root@iZbp1b61tux603e0rlumg5Z test]# vim parameter.sh
#!/bin/bash
echo $0 $1 $2
~
~
"parameter.sh" 8L, 53C
[root@iZbp1b61tux603e0rlumg5Z test]# sh parameter.sh 111 222
parameter.sh 111 222
2.$#
获取输入参数的个数
[root@iZbp1b61tux603e0rlumg5Z test]# vim parameter.sh
#!/bin/bash
echo $0 $1 $2
echo $#
~
~
"parameter.sh" 8L, 53C
[root@iZbp1b61tux603e0rlumg5Z test]# sh parameter.sh 111 222
parameter.sh 111 222
2
3.$*、$@
[root@iZbp1b61tux603e0rlumg5Z test]# vim parameter.sh
#!/bin/bash
echo $0 $1 $2
echo $#
echo $*
echo $@
~
~
[root@iZbp1b61tux603e0rlumg5Z test]# sh parameter.sh 1111 3333
parameter.sh 1111 3333
2
1111 3333
1111 3333
[root@iZbp1b61tux603e0rlumg5Z test]#
4.$?
最后一次执行的命令的返回状态,如果为0,证明上一个命令正确执行;如果非0,则证明上一个命令执行不正确
运算符
1)”$((运算式))“或"$[运算式]"
2)expr +,-,\*,/,% 加减乘除取余
expr运算符间要有空格
[root@iZbp1b61tux603e0rlumg5Z test]# expr 2 + 3
5
[root@iZbp1b61tux603e0rlumg5Z test]# expr 2+3
2+3
[root@iZbp1b61tux603e0rlumg5Z test]# expr 2+ 3
expr: syntax error
[root@iZbp1b61tux603e0rlumg5Z test]#
[root@iZbp1b61tux603e0rlumg5Z test]# expr `expr 2 + 3` \* 4
20
[root@iZbp1b61tux603e0rlumg5Z test]# s=$[(2+3)*4]
[root@iZbp1b61tux603e0rlumg5Z test]# echo $s
20
[root@iZbp1b61tux603e0rlumg5Z test]#
条件判断
[ condition ] (注意:condition前后要有空格)
常用判断条件
1)两个整数之间比较
= 字符串比较
-lt 小于(less than) -le 小于等于(less equal)
-eq 等于(equal) -ge 大于等于(greater equal)
-gt 大于 (greater than) -ne 不等于(not equal)
2)按照文件权限进行判断
-r 有读权限 -w 有写权限 -x 有执行权限
3)按照文件类型进行判断
-f 文件存在并且是一个常规文件
-e 文件存在
-d 文件存在并且是一个目录
if
[root@iZbp1b61tux603e0rlumg5Z test]# vim if.sh
#!/bin/bash
if [ $1 -eq 1 ]
then
echo "faker NO.1"
elif [ $1 -eq 2 ];then
echo "I am NO.1"
fi
~
~
~
[root@iZbp1b61tux603e0rlumg5Z test]# sh if.sh 1
faker NO.1
[root@iZbp1b61tux603e0rlumg5Z test]# sh if.sh 2
I am NO.1
[root@iZbp1b61tux603e0rlumg5Z test]#
case
[root@iZbp1b61tux603e0rlumg5Z test]# vim case.sh
#!/bin/bash
case $1 in
1)
echo "1111"
;;
2)
echo "2222"
;;
*)
echo "************"
;;
esac
~
[root@iZbp1b61tux603e0rlumg5Z test]# sh case.sh 1
1111
[root@iZbp1b61tux603e0rlumg5Z test]# sh case.sh 2
2222
[root@iZbp1b61tux603e0rlumg5Z test]# sh case.sh 3
************
[root@iZbp1b61tux603e0rlumg5Z test]#
for
[root@iZbp1b61tux603e0rlumg5Z test]# vim for.sh
#!/bin/bash
sum=0
for((i=1;i<=100;i++))
do
sum=$[$sum+$i]
done
echo $sum
~
~
[root@iZbp1b61tux603e0rlumg5Z test]# sh for.sh
5050
[root@iZbp1b61tux603e0rlumg5Z test]#
[root@iZbp1b61tux603e0rlumg5Z test]# vim for2.sh
#!/bin/bash
echo "============$=*======"
for i in $*
do
echo "传入的参数: $i"
done
echo "============$=@======"
for i in $@
do
echo "传入的参数: $i"
done
echo "======加引号后====$=*==="
for i in "$*"
do
echo "传入的参数: $i"
done
echo "======加引号后====$=@==="
for i in "$@"
do
echo "传入的参数: $i"
done
~
~
~
~
~
~
~
~
[root@iZbp1b61tux603e0rlumg5Z test]# sh for2.sh 123 321 111 222 333 444
============$=*======
传入的参数: 123
传入的参数: 321
传入的参数: 111
传入的参数: 222
传入的参数: 333
传入的参数: 444
============$=@======
传入的参数: 123
传入的参数: 321
传入的参数: 111
传入的参数: 222
传入的参数: 333
传入的参数: 444
======加引号后====$=*===
传入的参数: 123 321 111 222 333 444
======加引号后====$=@===
传入的参数: 123
传入的参数: 321
传入的参数: 111
传入的参数: 222
传入的参数: 333
传入的参数: 444
[root@iZbp1b61tux603e0rlumg5Z test]#
while
[root@iZbp1b61tux603e0rlumg5Z test]# vim while.sh
#!/bin/bash
s=0
i=1
while [ $i -le 100 ]
do
s=$[$s + $i]
i=$[$i + 1]
done
echo $s
~
~
[root@iZbp1b61tux603e0rlumg5Z test]# sh while.sh
5050
[root@iZbp1b61tux603e0rlumg5Z test]#
read读取控制台输入
read(选项)(参数)
选项:
-p: 指定读取值时的提示符
-t:指定读取值时等待的时间(秒)
[root@iZbp1b61tux603e0rlumg5Z test]# vim read.sh
#!/bin/bash
read -t 7 -p "input your name" NAME
echo $NAME
~
~
[root@iZbp1b61tux603e0rlumg5Z test]# sh read.sh
input your namelalala
lalala
[root@iZbp1b61tux603e0rlumg5Z test]#
函数
系统函数
1.basename
[root@iZbp1b61tux603e0rlumg5Z test]# basename /dev/test/faker.txt
faker.txt
[root@iZbp1b61tux603e0rlumg5Z test]# basename /dev/test/faker.txt .txt
faker
[root@iZbp1b61tux603e0rlumg5Z test]# basename /dev/test/faker.txt .tt
faker.txt
[root@iZbp1b61tux603e0rlumg5Z test]#
2.dirname
[root@iZbp1b61tux603e0rlumg5Z test]# dirname /dev/test/faker.txt
/dev/test
[root@iZbp1b61tux603e0rlumg5Z test]#
自定义函数
[root@iZbp1b61tux603e0rlumg5Z test]# vim sum.sh
#!/bin/bash
function sum()
{
s=0;
s=$[$1+$2]
echo $s
}
read -p "input your parameter1:" P1
read -p "input your parameter2:" P2
sum $P1 $P2
~
~
[root@iZbp1b61tux603e0rlumg5Z test]# sh sum.sh
input your parameter1:33
input your parameter2:44
77
[root@iZbp1b61tux603e0rlumg5Z test]#
shell工具
cut
cut[选项参数] fliename
-f 列号,提取第几列
-d 分隔符,按照指定分隔符分割列
[root@jingbo-dev test]# vim cut.txt
wo wo niu
hui ye bi
java hui bu
a scala
~
~
~
"cut.txt" [New] 5L, 46C written
[root@jingbo-dev test]#
//切割cut.txt第一列
[root@jingbo-dev test]# cut -d " " -f 1 cut.txt
wo
hui
java
a
[root@jingbo-dev test]#
//切割cut.txt第二列第三列
[root@jingbo-dev test]# cut -d " " -f 2,3 cut.txt
wo
ye
hui bu
[root@jingbo-dev test]#
//过滤出以java开头的一行 再以“ ”分割,取出第1列
[root@jingbo-dev test]# cat cut.txt |grep java
java hui bu
[root@jingbo-dev test]# cat cut.txt |grep java| cut -d " " -f 1
java
[root@jingbo-dev test]#
//过滤出以java开头的一行 再以“ ”分割,取出第2列及以后
[root@jingbo-dev test]# cat cut.txt |grep java| cut -d " " -f 2-
hui bu
[root@jingbo-dev test]#
sed
sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,成为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
sed [选项参数] ‘command’ filename
选项参数:
-e :直接在指令列模式上进行sed的动作编辑。
命令:
a:新增,a的后面可以接字符串,在下一行出现
d:删除
s:查找并替换
//在第三行后面加lalala,源文件并没改变
[root@iZbp1b61tux603e0rlumg5Z test]# vim sed.txt
java c
hadoop scala hive
hbase spark
mysql kafka zk
~
[root@iZbp1b61tux603e0rlumg5Z test]# sed "3a lalala" sed.txt
java c
hadoop scala hive
lalala
hbase spark
mysql kafka zk
[root@iZbp1b61tux603e0rlumg5Z test]# cat sed.txt
java c
hadoop scala hive
hbase spark
mysql kafka zk
[root@iZbp1b61tux603e0rlumg5Z test]#
//删除包含“java”的一行
[root@iZbp1b61tux603e0rlumg5Z test]# sed "/java/d" sed.txt
hadoop scala hive
hbase spark
mysql kafka zk
[root@iZbp1b61tux603e0rlumg5Z test]#
[root@iZbp1b61tux603e0rlumg5Z test]# cat sed.txt
java c
hadoop scala hive
hbase spark
mysql kafka zk
[root@iZbp1b61tux603e0rlumg5Z test]#
//查找hadoop并将其替换为hdfs,g表示全局
[root@iZbp1b61tux603e0rlumg5Z test]# sed "s/hadoop/hdfs/g" sed.txt
java c
hdfs scala hive
hbase spark
mysql kafka zk
[root@iZbp1b61tux603e0rlumg5Z test]#
[root@iZbp1b61tux603e0rlumg5Z test]# cat sed.txt
java c
hadoop scala hive
hbase spark
mysql kafka zk
[root@iZbp1b61tux603e0rlumg5Z test]#
//多个指令
//删除第三行,并查找替换hadoop为hdfs
[root@iZbp1b61tux603e0rlumg5Z test]# sed -e "3d" -e "s/hadoop/hdfs/g" sed.txt
java c
hdfs scala hive
hbase spark
mysql kafka zk
[root@iZbp1b61tux603e0rlumg5Z test]#
awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
用法
awk [选项参数] ‘patternl{action1}’ …’ filename
pattern:表示AWK在数据中查找的内容,就是匹配模式
action:在找到匹配内容时所执行的一系列命令
选项参数:
-F:指定输入文件分隔符
-v:赋值一个用户定义变量
[root@iZbp1b61tux603e0rlumg5Z test]# cat passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin
systemd-network:x:998:996:systemd Network Management:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
polkitd:x:997:995:User for polkitd:/:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
nginx:x:996:994:Nginx web server:/var/lib/nginx:/sbin/nologin
[root@iZbp1b61tux603e0rlumg5Z test]#
//以上是从/etc/passwd cp过来的文件
//搜索passwd文件以root开头的所有行,并输出该行的第7列
[root@iZbp1b61tux603e0rlumg5Z test]# awk -F : '/^root/ {print $7}' passwd
/bin/bash
[root@iZbp1b61tux603e0rlumg5Z test]#
//搜索passwd文件以root开头的所有行,并输出该行的第1,7列
[root@iZbp1b61tux603e0rlumg5Z test]# awk -F : '/^root/ {print $1','$7}' passwd
root /bin/bash
[root@iZbp1b61tux603e0rlumg5Z test]# awk -F : '/^root/ {print $1","$7}' passwd
root,/bin/bash
[root@iZbp1b61tux603e0rlumg5Z test]#
//将文件中用户id增加1
[root@iZbp1b61tux603e0rlumg5Z test]# awk -F : -v i=1 '{print $3+i}' passwd
1
2
3
4
5
6
7
8
9
12
13
15
100
171
1000
999
82
998
60
90
75
39
997
[root@iZbp1b61tux603e0rlumg5Z test]#
awk的内置变量
FILENAME:文件名
NR:已读的记录数
NF:浏览记录的域的个数(即切割后,列的个数)
[root@iZbp1b61tux603e0rlumg5Z test]# awk -F : '{print FILENAME "," NR "," NF}' passwd
passwd,1,7
passwd,2,7
passwd,3,7
passwd,4,7
passwd,5,7
passwd,6,7
passwd,7,7
passwd,8,7
passwd,9,7
passwd,10,7
passwd,11,7
passwd,12,7
passwd,13,7
passwd,14,7
passwd,15,7
passwd,16,7
passwd,17,7
passwd,18,7
passwd,19,7
passwd,20,7
passwd,21,7
passwd,22,7
passwd,23,7
[root@iZbp1b61tux603e0rlumg5Z test]#
sort
将文件进行排序,并将排序结果标准输出。
基本语法
sort(选项)(参数)
-n:依照数值的大小排序
-r:以相反的顺序来排序
-t:设置排序时所用的分隔字符
-k:指定需要排序的列
[root@iZbp1b61tux603e0rlumg5Z test]# vim sort.sh
bb:40:4:9
bs:50:3:9
xz:20:9:7
ss:30:9:7
ccc:23:5:6
~
"sort.sh" [New] 5L, 51C written
[root@iZbp1b61tux603e0rlumg5Z test]# sort -t : -nrk 2 sort.sh
bs:50:3:9
bb:40:4:9
ss:30:9:7
ccc:23:5:6
xz:20:9:7
[root@iZbp1b61tux603e0rlumg5Z test]#