一、shell概述
[root@localhost ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
/bin/tcsh
/bin/csh
一个简单的入门
[root@localhost ~]# ls
aa Hello.java original-ks.cfg
anaconda-ks.cfg mysql-community-release-el7-5.noarch.rpm
[root@localhost ~]# mkdir shell
[root@localhost ~]# cd shell/
[root@localhost shell]# touch hello.sh
[root@localhost shell]# vim hello.sh
[root@localhost shell]# ls
hello.sh
[root@localhost shell]# bash hello.sh
helloworld
补:hello.sh里面的内容
注意权限
[root@localhost shell]# ./hello.sh
-bash: ./hello.sh: 权限不够
[root@localhost shell]# chmod +x ./hello.sh
[root@localhost shell]# ll
总用量 4
-rwxr-xr-x. 1 root root 31 7月 14 04:01 hello.sh
[root@localhost shell]# ./hello.sh
helloworld
./相对路径比较常用
其他执行方法
[root@localhost shell]# source hello.sh
helloworld
[root@localhost shell]# source /root/shell/hello.sh
helloworld
[root@localhost shell]# . hello.sh
helloworld
[root@localhost shell]# type source
source 是 shell 内嵌
二、变量
全局变量
局部变量
局部变量只对自己有效对外面的没有效
env:查看所有的环境变量
- 自定义变量
等号左右不能有空格
有空格加引号
[root@localhost shell]# a=2
[root@localhost shell]# echo $2
[root@localhost shell]# echo $a
2
[root@localhost shell]# my_1=hello
[root@localhost shell]# echo $my_1
hello
定义只读
readonly b=5
撤销
unset 要撤销的文件
只读的变量不能撤销
局部变量提升为全局变量
export 变量名
- 特殊变量
$n:1-9代表参数,10以上用{10},$0代表脚本本身名称。
$#:获取输入参数的个数
$*:所有参数,把参数看作一个整体
$@:所有参数,把参数区分对待
parameter里的内容:
#!/bin/bash
echo '====$n===='
echo script name:$0
echo 1st parameter :$1
echo 2nd parameter :$2
echo '====$#===='
echo parameter numbers:$#
echo '====$*===='
echo $*
echo '====$@===='
echo $@
[root@localhost shell]# /root/shell/parameter abc def
====$n====
script name:/root/shell/parameter
1st parameter :abc
2nd parameter :def
====$#====
parameter numbers:2
====$*====
abc def
====$@====
abc def
$?
正常执行返回0
不正常返回127
[root@localhost shell]# echo $?
0
[root@localhost shell]# parameter
bash: parameter: 未找到命令...
[root@localhost shell]# echo $?
127
三、运算符
[root@localhost ~]# echo $[1+2]
3
[root@localhost ~]# echo $((1+2))
3
[root@localhost ~]# a=$[6+8]
[root@localhost ~]# echo a
a
简单加法
add.sh
#!/bin/bash
sum=$[$1+$2]
echo sum=$sum
[root@localhost ~]# vim add.sh
[root@localhost ~]# chmod +x add.sh
[root@localhost ~]# ll add.sh
-rwxr-xr-x. 1 root root 39 7月 14 18:37 add.sh
[root@localhost ~]# echo add.sh
add.sh
[root@localhost ~]# ./add.sh
./add.sh:行2: +: 语法错误: 期待操作数 (错误符号是 "+")
sum=
[root@localhost ~]# ./add.sh 5 9
sum=14
四、条件判断
- 常用判断条件
- 两个整数之间比较
-eq 等于(equal)
-ne 不等于(not equal)
-lt 小于(less than)
-le 小于等于(less equal)
-gt大于(greater than)
-ge大于等于(greater equal)
!=不等于 - 文件权限
-r读
-w写
-x执行 - 文件类型
-e文件存在(existence)
-f文件存在并且是一个常规的文件(file)
-d文件存在并且是一个目录(directory)
- 两个整数之间比较
注意:test等号两边得有空格
0为真
1为假
[root@localhost ~]# a=hello
[root@localhost ~]# echo $a
hello
[root@localhost ~]# test $a = hello
[root@localhost ~]# echo $?
0
[root@localhost ~]# test $a = Hello
[root@localhost ~]# echo $?
1
或者
[root@localhost ~]# [ $a = hello ]
[root@localhost ~]# echo $?
0
- 多条件判断
&&:前一条命令执行成功时,才执行后一条命令
||:上一条命令执行失败后,才执行下一条指令
[root@localhost shell]# a=8
[root@localhost shell]# [ $a -gt 5 ] && echo "$a < 5" ||echo "$a > 5"
8 < 5
[root@localhost shell]# a=4
[root@localhost shell]# [ $a -gt 5 ] && echo "$a < 5" ||echo "$a > 5"
4 > 5
五、流程控制
- if 判断
单分支
[root@localhost shell]# a=25
[root@localhost shell]# if [ $a -gt 18 ] && [ $a -lt 23 ]; then echo ok; fi
[root@localhost shell]# echo $a
25
if else
test.sh脚本里的内容
#!/bin/bash
if [ "$1"x = "atguigu"x ]
then
echo "welcome,atguigu"
fi
#输入第二个
if [ $2 -lt 18 ]
then
echo "未成年人"
else
echo "成年人"
fi
[root@localhost shell]# ./test.sh atguigu 18
welcome,atguigu
成年人
if elif 多分支
#!/bin/bash
if [ "$1"x = "atguigu"x ]
then
echo "welcome,atguigu"
fi
#输入第二个
if [ $2 -lt 18 ]
then
echo "未成年人"
elif [ $2 -lt 35 ]
then
echo "青年人"
else
echo "成年人"
fi
[root@localhost shell]# ./test.sh atguigu 27
welcome,atguigu
青年人
- case 语句
case_test.sh vim 内容
#!/bin/bash
case $1 in
1)
echo "one"
;;
2)
echo "two"
;;
3)
echo "three"
;;
*)
echo "number else"
;;
esac
[root@localhost shell]# ./case_test.sh 2
two
- 循环
for语句
#!/bin/bash
for ((i=1;i <= $1; i++ ))
do
sum=$[ $sum + $i ]
done
echo $sum
注意:双小括号可以直接使用数学表达式
[root@localhost shell]# vim sum_to.sh
[root@localhost shell]# chmod +x sum_to.sh
[root@localhost shell]# ./sum_to.sh 100
5050
第二种语法
[root@localhost shell]# for os in windows mac linux ; do echo $os ; done
windows
mac
linux
[root@localhost shell]# for i in {1..100}; do sum=$[$sum+$i];done;echo $sum
5050
parameter:范围;参数;决定因素
- while 循环
vim内容
# while 实现循环
a=1
while [ $a -le $1 ]
do
sum2=$[ $sum2 + $a ]
a=$[ $a +1 ]
done
echo $sum2
[root@localhost shell]# ./sum_to.sh 100
5050
5050
或者
六、读取控制台输入
- read
-p:指定读取值时的提示符
-t:指定读取值时等待的时间(秒)如果不加则一直等待- 参数
变量:指定读取值的变量名
- 参数
read -t 10 -p "请输入你的芳名" name
echo "welcome, $name"
结果
[root@localhost shell]# ./read_test.sh 1
请输入你的芳名4
welcome, 4
七、函数
- basename
对文件做剪切
空格.sh :去后缀
[root@localhost shell]# basename /root/shell/parameter.sh
parameter.sh
[root@localhost shell]# basename /root/shell/parameter.sh.sh
parameter.sh.sh
[root@localhost shell]# basename /root/shell/parameter.sh .sh
parameter
parameter.sh 里
echo script name:$(basename $0 .sh)
- dirname 文件绝对路径
取文件路径的绝对路径名称
echo shell name:$(basename $0 .sh)
echo shell path: $(cd $(dirname $0); pwd)
绝对路径显示
[root@localhost shell]# ./parameter.sh abc
====$n====
shell name:parameter
shell path: /root/shell
- 自定义函数
function add(){
s=$[ $1 + $2 ]
echo $s
}
read -p "请输入第一个数" a
read -p "请输入第二个数" b
sum=$(add $a $b)
echo $sum
结果
[root@localhost shell]# vim fun_test.sh
[root@localhost shell]# ./fun_test.sh
请输入第一个数586
请输入第二个数7
593
八、综合应用-文件归档
vim daily_archive.sh
if [ $# -ne 1 ]
then
echo "参数个数错误!应该输入一个参数,作为归档目录名"
exit
fi
# 从参数中获取目录名称
if [ -d $1 ]
then
echo
else
echo
echo "目录不存在"
echo
exit
fi
DIR_NAME=$(basename $1)
DIR_PATH=$(cd $(dirname $1); pwd)
# 获取当前日期
DATE=$(date +%y%m%d)
# 定义生成的归档文件名称
FILE=archive_${DIR_NAME}_SDATE.tar.gz
DEST=/root/archive/$FILE
# 开始归档目录文件
echo "开始归档..."
echo
tar -czf $DEST $DIR_PATH/$DIR_NAME
if [ $? -eq 0 ]
then
echo
echo "归档成功!"
echo "归档文件为:$DEST"
else
echo "归档出现问题 "
echo
fi
exit
结果
[root@localhost shell]# mkdir /root/archive
[root@localhost shell]# ./daily_archive.sh ../shell
开始归档...
tar: 从成员名中删除开头的“/”
归档成功!
归档文件为:/root/archive/archive_shell_SDATE.tar.gz
九、正则表达式
^
查询一行的开头
[root@localhost shell]# cat /etc/passwd | grep ^a
adm:x:3:4:adm:/var/adm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
$
匹配一行的结束
[root@localhost shell]# cat /etc/passwd | grep t$
halt:x:7:0:halt:/sbin:/sbin/halt
r…t
匹配r和t中间隔两个字符
[root@localhost shell]# cat /etc/passwd | grep r..t
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
:*
*前面的出现任意多次
[root@localhost shell]# cat /etc/passwd | grep ro*t
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
grep ^a.*in$
以a开头,以in结尾
[root@localhost shell]# cat /etc/passwd | grep ^a.*in$
adm:x:3:4:adm:/var/adm:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
[]
[root@localhost shell]# cat /etc/passwd | grep r[a,b]t
operator:x:11:0:operator:/root:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
" \ "
转义字符
[root@localhost shell]# cat daily_archive.sh | grep '\$'
if [ $# -ne 1 ]
if [ -d $1 ]
DIR_NAME=$(basename $1)
DIR_PATH=$(cd $(dirname $1); pwd)
DATE=$(date +%y%m%d)
FILE=archive_${DIR_NAME}_SDATE.tar.gz
DEST=/root/archive/$FILE
tar -czf $DEST $DIR_PATH/$DIR_NAME
十、文本处理工具
cut
截取空格之后的一列
[root@localhost shell]# vim cut.txt
[root@localhost shell]# cut -d " " -f 1 cut.txt
zhangsan
wangwu
wangamzi
[root@localhost shell]# cat cut.txt
zhangsan hh
wangwu hh
wangamzi hh
[root@localhost shell]# cut -d " " -f 1 cut.txt
zhangsan
wangwu
wangamzi
截取2和3列
[root@localhost shell]# cut -d " " -f 2,3 cut.txt
hh
hh
hh
awk
root开头的行,输出第1列和第7列
[root@localhost shell]# cat /etc/passwd | awk -F ":" '/^root/ {print $1","$7}'
root,/bin/bash
前面加东西,后面加东西
[root@localhost shell]# cat /etc/passwd | awk -F ":" 'BEGIN{print "user,shell"} {print $1","$7} END{"end of file"}'
user,shell
root,/bin/bash
bin,/sbin/nologin
用户id增加数值1
[root@localhost shell]# cat /etc/passwd | awk -F ":" ' {print $3}'0
1
2
3
4
5
6
7
[root@localhost shell]# cat /etc/passwd | awk -F ":" ' {print $3+1}'
1
2
3
4
使用自定义变量
[root@localhost shell]# cat /etc/passwd | awk -v i=2 -F ":" ' {print $3+i}'
2
3
4
输出行号和列数
[root@localhost shell]# cat /etc/passwd | awk -F ":" '{print " file" FILENAME " 行号" NR "列数" NF}'
file- 行号1列数7
file- 行号2列数7
file- 行号3列数7