shell基础
1.history:查看历史命令
(1)#!!命令效果等同于#history
(2)#!+编号,执行历史命令中对应编号的命令
2.alias+别名,用于别名的设定
unalias+别名,用于撤销别名的设定
3.通配符的使用
[root@server1 mnt]# ls
1.txt 2.txt txt
[root@server1 mnt]# ls *.txt
1.txt 2.txt
[root@server1 mnt]# ls ?.txt
1.txt 2.txt
[root@server1 mnt]# ls [12].txt
1.txt 2.txt
[root@server1 mnt]# ls *txt
1.txt 2.txt txt
[root@server1 mnt]# ls ?txt
ls: cannot access ?txt: No such file or directory
>:重定向
>>:追加
<:反向重定向
2>:错误重定向
[root@server1 mnt]# ls file
ls: cannot access file: No such file or directory
[root@server1 mnt]# ls file 2> error.txt
[root@server1 mnt]# cat error.txt
ls: cannot access file: No such file or directory
2>>:追加错误重定向
|:管道符,将前者输出的内容作为后者内容的输入
ctrl+z:暂停进程
ctrl+c:终止进程
4.shell变量
(1)系统变量,如:$HOME、$PATH、$HOSTNAME...
(2)自定义变量:如,a=1,$a
#env,打印出系统环境变量
#set,列出所有的变量
#export a=1,声明全局变量a,使其在子shell中也生效
#unset a,取消a的全局声明
[root@server1 mnt]# a=1
[root@server1 mnt]# echo $a
1
[root@server1 mnt]# bash
[root@server1 mnt]# echo $a
[root@server1 mnt]# export a=1
[root@server1 mnt]# bash
[root@server1 mnt]# echo $a
1
(3)变量的命名:只能包含数字、字母和下划线,但是不能以数字开头
(4)` `、' '、" "三种符号用法的比较:
` `:反引号表示引用
[root@server1 mnt]# a=123
[root@server1 mnt]# b=`echo $a`
[root@server1 mnt]# echo $b
123
' ':单引号可以屏蔽特殊字符的功能
[root@server1 mnt]# b='echo $a'
[root@server1 mnt]# echo $b
echo $a
" ":双引号的强度弱於单引号
[root@server1 mnt]# b="echo $a"
[root@server1 mnt]# echo $b
echo 123
5.命令提示符的表示
(1)[root@server1 mnt]# echo $PS1
[\u@\h \W]\$
\u=username,表示用户名
\h=hostname,表示主机名
\w=path,表示当前路经
\$=[$#],表示当前用户身份
(2)修改名命令提示符格式
[root@server1 mnt]# PS1='[\h@\u \w] \$ '
[server1@root /mnt] # cd /etc/init.d/
[server1@root /etc/init.d] #
6./etc/profile、/etc/bashrc、.bash_profile、.bashrc四个文件的区别
(1)/etc/profile和/etc/bashrc作用于系统全局,而.bash_profile、.bashrc作用于当前用户
(2)/etc/profile、.bash_profile作为用户登录系统时执行的文件;
/etc/bashrc、.bashrc作为打开shell时执行的文件;
[root@server1 ~]# echo 'echo "bashrc"' >> .bashrc
[root@server1 ~]# cat .bashrc
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
echo "bashrc
----------------------------------------------------------------------
[root@server1 ~]# echo 'echo "profile"' >> .bash_profile
[root@server1 ~]# cat .bash_profile
# .bash_profile
# Get the aliases and functions
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
# User specific environment and startup programs
PATH=$PATH:$HOME/bin
export PATH
echo "profile"
----------------------------------------------------------------------
[root@server1 ~]# bash
bashrc
[root@server1 ~]# su -
bashrc
profile
6.shell命令
(1)cut,分隔符
[root@server1 ~]# cut -d ':' -f 1 /etc/passwd
root
bin
daemon
adm
lp
...
-d:指定分隔符
-f:指定段数,如,1-3第一段至第三段;1,3第一段和第三段
-c:指定分割的字符数
[root@server1 ~]# cut -c 1,3 /etc/passwd
ro
bn
de
...
(2)sort,排序(默认按AIISC码排序)
-t:指定分隔符
-k:指定第几段
-n:按数字大小排序
-r:逆向排序
-u:去重复显示
-c:统计重复次数
(3)|,管道符
[root@server1 ~]# sort -t ':' -k 3 -n /etc/passwd | cut -d ':' -f 3
0
1
2
3
...
--------------------------------------------------------
[root@server1 ~]# cp /etc/passwd 1.txt
[root@server1 ~]# cut -d ':' -f 3 1.txt| sort -n |uniq -c
1 0
2 1
1 2
....
(4)wc:统计命名
[root@server1 ~]# wc 1.txt
27 36 1159 1.txt
[root@server1 ~]# wc -l 1.txt
27 1.txt
----------------------------------------------------
[root@server1 ~]# cd /mnt/
[root@server1 mnt]# cat -A 2.txt
1$
2$
[root@server1 mnt]# line=`wc -l 2.txt | cut -d ' ' -f 1`;echo $line
2
[root@server1 mnt]# if [ $line -lt "3" ];then echo "no";fi
no
(5)tee,类似于>,将结果重定向于指定文件中并且将结果显示到屏幕上
(6)tr,用于替换。如,
#ls | tr 'a-z' 'A-Z' 将ls结果中的小写字母全部替换为大写字母
(7)split,文件分割
[root@server1 mnt]# > 1.txt
[root@server1 mnt]# for i in `seq 1 1000`;do cat /etc/passwd >> 1.txt ;done
[root@server1 mnt]# mkdir test
[root@server1 mnt]# mv 1.txt test/
[root@server1 mnt]# cd test/
[root@server1 test]# ls
1.txt
[root@server1 test]# du -sh 1.txt
1.1M1.txt
[root@server1 test]# du -sb 1.txt
10580001.txt
[root@server1 test]# split -l 1000 1.txt zhang #按照指定的行数分割
[root@server1 test]# ls
1.txt zhangae zhangaj zhangao zhangat
....
[root@server1 test]# ls zhang* | xargs -i mv {} {}.txt
[root@server1 test]# ls
1.txt zhangai.txt zhangar.txt
zhangaa.txt zhangaj.txt zhangas.txt
.....
[root@server1 test]# wc -l *
24000 1.txt
1000 zhangaa.txt
1000 zhangab.txt
1000 zhangac.txt
.....
---------------------------------------------------
[root@server1 test]# rm -fr zhang*
[root@server1 test]# ls
1.txt
[root@server1 test]# split -b 1M 1.txt #按照大小进行分割
[root@server1 test]# ls
1.txt xaa xab
[root@server1 test]# du -sh *
1.1M1.txt
1.0Mxaa
12Kxab
7.正则表达式
(1)grep
-r:遍历
-c:统计匹配到的行数
-n:列出匹配行的行号及其内容
-o:列出匹配到的关键字
-v:列出没有被匹配到的内容
[root@server1 mnt]# cp /etc/passwd 1.txt
[root@server1 mnt]# grep -c 'root' 1.txt
2
[root@server1 mnt]# grep -n 'root' 1.txt
1:root:x:0:0:root:/root:/bin/bash
11:operator:x:11:0:operator:/root:/sbin/nologin
[root@server1 mnt]# grep -n --color 'root' 1.txt
1:root:x:0:0:root:/root:/bin/bash
11:operator:x:11:0:operator:/root:/sbin/nologin
[root@server1 mnt]# grep -o 'root' 1.txt
root
root
root
root
[root@server1 mnt]# grep -o 'root' 1.txt | wc -l
4
grep中常用的通配符:
*:匹配该符号前面的字符零个或多个
.:匹配当前位置任意字符
?:匹配该符号前面的字符零个或一个,通常和-E配合使用,亦可使用egrep
+:匹配该符号前面的字符一个或多个,通常和-E配合使用,亦可使用egrep
(2)sed,匹配与替换
-n:屏蔽掉匹配行之外的内容
-e:查找多个匹配字符需要用此选项
-r:延伸正则表达式用法,不用转义,即不必使用拓义符\
[root@server1 mnt]# sed -n '1p' 1.txt #p表示打印
root:x:0:0:root:/root:/bin/bash
[root@server1 mnt]# grep -n '.*' 1.txt | sed -n '1p'
1:root:x:0:0:root:/root:/bin/bash
[root@server1 mnt]# grep -n '.*' 1.txt | sed -n '/root/p'
1:root:x:0:0:root:/root:/bin/bash
11:operator:x:11:0:operator:/root:/sbin/nologin
------------------------------------------------------------------------------
[root@server1 mnt]# grep -n '.*' 1.txt | sed -r '/n$/d' #d表示删除
1:root:x:0:0:root:/root:/bin/bash
6:sync:x:5:0:sync:/sbin:/bin/sync
8:halt:x:7:0:halt:/sbin:/sbin/halt
--------------------------------------------------------------------------------
[root@server1 mnt]# head -3 1.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@server1 mnt]# head -3 1.txt | sed -r 's/([^:]+)(:.*:)([^:]+$)/\3\2\1/'
/bin/bash:x:0:0:root:/root:root
/sbin/nologin:x:1:1:bin:/bin:bin
/sbin/nologin:x:2:2:daemon:/sbin:daemon
(3)awk命令
[root@server1 mnt]# awk -F ':' '$1 ~ /root/' 1.txt
root:x:0:0:root:/root:/bin/bash
[root@server1 mnt]# awk -F ':' '$1 ~ /root/ {print $3,$4}' 1.txt
0 0
[root@server1 mnt]# awk -F ':' '$1 ~ /root/ {OFS="#";print $1,$2}' 1.txt
root#x
[root@server1 mnt]# awk -F ':' '$1=="root" {print $1,$2}' 1.txt
root x
[root@server1 mnt]# awk -F ':' '$1=="root" || NR>20 {print $1,$2}' 1.txt
root x
saslauth x
postfix x
sshd x
tcpdump x
[root@server1 mnt]# awk -F ':' '$1=="root" && NR>20 {print $1,$2}' 1.txt
[root@server1 mnt]# awk -F ':' '$1=$3+$4 {print $0}' 1.txt
2 x 1 1 bin /bin /sbin/nologin
4 x 2 2 daemon /sbin /sbin/nologin
....
-----------------------------------------------------------------
[root@server1 mnt]# awk -F ':' 'NF>3 && NF<8 {print $0}' 1.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
....
-------------------------------------------------------------------
[root@server1 mnt]# awk -F ':' 'NF>3 && NR<4 {print $0}' 1.txt #NF表示段数,NR表示行数
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@server1 mnt]# awk -F ':' '$1=1 {OFS=":"; print $0}' 1.txt #OFS自定义分隔符
1:x:0:0:root:/root:/bin/bash
1:x:1:1:bin:/bin:/sbin/nologin
1:x:2:2:daemon:/sbin:/sbin/nologin
.....
8.shell编程
(1)示例一
[root@server1 mnt]# mkdir shell
[root@server1 mnt]# cd shell/
[root@server1 shell]# cat 1.sh
#!/bin/bash
#这是第一个shell脚本
echo "[root@server1 shell]# sh 1.sh #第一种执行方法
欢迎进入shell编程
[root@server1 shell]# chmod +x 1.sh #第二种执行方法
[root@server1 shell]# ./1.sh
欢迎进入shell编程
[root@server1 shell]# /mnt/shell/1.sh #第三种执行方法
欢迎进入shell编程
[root@server1 shell]# bash -x 1.sh #此方法可以查看脚本的执行过程
+ echo $'\346\254\242\350\277\216\350\277\233\345\205\245shell\347\274\226\347\250\213'
欢迎进入shell编程
-----------------------------------------------------------------------------
(2)date
[root@server1 shell]# date
Mon Mar 13 15:45:49 CST 2017
[root@server1 shell]# date +%Y
2017
[root@server1 shell]# date +%y
17
[root@server1 shell]# date +%M
46
[root@server1 shell]# date +%m
03
[root@server1 shell]# date +%D
03/13/17
[root@server1 shell]# date +%d
13
[root@server1 shell]# date +%H
15
[root@server1 shell]# date +%h
Mar
[root@server1 shell]# date +%S
25
[root@server1 shell]# date +%s
1489391258
[root@server1 shell]# date -d @100
Thu Jan 1 08:01:40 CST 1970
[root@server1 shell]# date +%F
2017-03-13
[root@server1 shell]# date +%T
15:48:25
[root@server1 shell]# date +"%Y-%m-%d %H:%M:%S"
2017-03-13 15:55:46
---------------------------------------------------------------
[root@server1 shell]# date -d "-1 day" +"%F %T"
2017-03-12 16:01:08
[root@server1 shell]# date -d "+1 day" +"%F %T"
2017-03-14 16:01:17
[root@server1 shell]# date -d "+1 month" +"%F %T"
2017-04-13 16:01:31
[root@server1 shell]# date -d "+1 year" +"%F %T"
2018-03-13 16:01:43
[root@server1 shell]# date -d "+1 week" +"%F %T"
2017-03-20 16:01:56
[root@server1 shell]# date -d "+10 hour" +"%F %T"
2017-03-14 02:03:47
[root@server1 shell]# date -d "+10 min" +"%F %T"
2017-03-13 16:13:55
[root@server1 shell]# date -d "+10 sec" +"%F %T"
2017-03-13 16:04:11
---------------------------------------------------------------------
(3)shell变量
[root@server1 shell]# vim 2.sh
[root@server1 shell]# cat 2.sh
#!/bin/bash
#用户交互脚本
read -p "请输入一个数字:" num
echo $num
#也可使用以下方式:
#read -p "请输入一个数字:"
#echo $REPLY
[root@server1 shell]# sh 2.sh
请输入一个数字:10
10
---------------------------------------------------
[root@server1 shell]# vim 3.sh
[root@server1 shell]# cat 3.sh
#!/bin/bash
#内置变量的使用
echo "\$1=$1"
echo "\$2=$2"
echo "\$3=$3"
echo "\$#=$#"
echo "\$0=$0"
[root@server1 shell]# sh 3.sh zhang westos 1 2
$1=zhang
$2=westos
$3=1
$#=4
$0=3.sh
-----------------------------------------------------------
[root@server1 shell]# a=1;b=3
[root@server1 shell]# c=$[$a+$b]
[root@server1 shell]# echo $c
4
-----------------------------------------------------------
(4)if语句
[root@server1 shell]# vim if1.sh
[root@server1 shell]# cat if1.sh
#!/bin/bash
a=1
if [ $a == 2 ];then
echo true
else
echo false
fi
[root@server1 shell]# sh if1.sh
false
[root@server1 shell]# sh -x if1.sh
+ a=1
+ '[' 1 == 2 ']'
+ echo false
false
-------------------------------------------------------------------------------
[root@server1 shell]# a=5
[root@server1 shell]# if [ $a -lt 10 ] && [ $a -gt 3 ]; then echo ok; else echo no; fi
ok
[root@server1 shell]# if (($a<3)); then echo ok; else echo no;fi
no
[root@server1 shell]# if [ $a -lt 6 -o $a -gt 8 ]; then echo ok; else echo no; fi
ok
----------------------------------------------------------------------------------------------------
[root@server1 shell]# vim if2.sh
[root@server1 shell]# cat if2.sh
#!/bin/bash
read -p "请输入一个数字:" n
n1=`echo $n |grep -c '[^0-9]'`
if [ $n1 -eq 1 ];then
echo "请重新输入!"
exit
fi
n2=$[$n%2]
if [ $n2 == 0 ];then
echo "这是偶数!"
else
echo "这是奇数!"
fi
[root@server1 shell]# sh if2.sh
请输入一个数字:23456
这是偶数!
[root@server1 shell]# sh if2.sh
请输入一个数字:ag56
请重新输入!
[root@server1 shell]# sh if2.sh
请输入一个数字:133131
这是奇数!
-----------------------------------------------------------------------
(5)date的使用
[root@server1 shell]# vim date1.sh
[root@server1 shell]# cat date1.sh
#!/bin/bash
n=`date +%F`
exec >/mnt/$n.log 2>&1
echo "Begin at `date`"
ls /mnt/zhang
cd /tmp/haha
echo "End at `date`"
[root@server1 shell]# sh date1.sh
[root@server1 shell]# cat /mnt/2017-03-13.log
Begin at Mon Mar 13 21:04:59 CST 2017
ls: cannot access /mnt/zhang: No such file or directory
date1.sh: line 8: cd: /tmp/haha: No such file or directory
End at Mon Mar 13 21:04:59 CST 2017
-------------------------------------------------------------------------
(6)case语句
[root@server1 shell]# vim if3.sh
[root@server1 shell]# cat if3.sh
#!/bin/bash
read -p "请输入一个数字:" n
n1=`echo $n |sed 's/[0-9]//g'`
if [ ! -z $n1 ];then
echo "请重新输入!"
exit
fi
n2=$[$n%2]
case $n2 in
0)
echo "偶数"
;;
1)
echo "奇数"
;;
*)
echo "请重新输入!"
;;
esac
[root@server1 shell]# sh if3.sh
请输入一个数字:345
奇数
[root@server1 shell]# sh if3.sh
请输入一个数字:666
偶数
[root@server1 shell]# sh if3.sh
请输入一个数字:ab56
请重新输入!
---------------------------------------------------------
[root@server1 shell]# vim if4.sh
[root@server1 shell]# cat if4.sh
#!/bin/bash
read -p "请输入一个数字:" n
n1=`echo $n |sed 's/[-0-9]//g'`
if [ ! -z $n1 ];then
echo "请重新输入!"
exit
fi
if [ $n -lt 60 ];then
tag=1
elif [ $n -ge 60 ] && [ $n -lt 80 ];then
tag=2
elif [ $n -ge 80 ] && [ $n -lt 90 ];then
tag=3
elif [ $n -ge 90 ] && [ $n -le 100 ];then
tag=4
fi
case $tag in
1)
echo "不及格"
;;
2)
echo "及格"
;;
3)
echo "良好"
;;
4)
echo "优秀"
;;
*)
echo "请输入0-100的数字!"
;;
esac
[root@server1 shell]# sh if4.sh
请输入一个数字:110
请输入0-100的数字!
[root@server1 shell]# sh if4.sh
请输入一个数字:98
优秀
[root@server1 shell]# sh if4.sh
请输入一个数字:85
良好
[root@server1 shell]# sh if4.sh
请输入一个数字:70
及格
[root@server1 shell]# sh if4.sh
请输入一个数字:50
不及格
-----------------------------------------------------------------------------------
(7)for循环
[root@server1 shell]# vim for1.sh
[root@server1 shell]# cat for1.sh
#!/bin/bash
sum=0
for i in `seq 1 100`
do
sum=$[$sum+$i]
done
echo $sum
[root@server1 shell]# sh for1.sh
5050
------------------------------------------------------------------
[root@server1 shell]# vim for2.sh
[root@server1 shell]# cat for2.sh
#!/bin/bash
for i in `ls /mnt/`
do
if [ -d /mnt/$i ];then
echo "/mnt/$i"
fi
done
[root@server1 shell]# sh for2.sh
/mnt/shell
/mnt/test
[root@server1 shell]# cd /mnt/
[root@server1 mnt]# ls
1.txt 2.txt file1 test
2017-03-13.log error.txt shell txt
(8)while循环
[root@server1 shell]# vim while1.sh
[root@server1 shell]# cat while1.sh
#!/bin/bash
w|cat > 1.txt
while :
do
load=`cat 1.txt|head -1|awk -F 'load average: ' '{print $2}'|cut -d. -f1`
if [ $load -gt 10 ];then
top|mail -s "系统负载过高:$load" [email protected]
fi
sleep 30
done
--------------------------------------------------------------------------
[root@server1 shell]# vim while2.sh
[root@server1 shell]# cat while2.sh
#!/bin/bash
while :
do
read -p "请输入数字:" n
if [ -z $n ];then
echo "请输入数字!"
continue
fi
n1=`echo $n|sed 's/[-0-9]//g'`
if [ ! -z $n1 ];then
echo "请重新输入!"
continue
fi
break
done
echo $n
[root@server1 shell]# sh while2.sh
请输入数字:12ab
请重新输入!
请输入数字:
请输入数字!
请输入数字:123
123
(9)continue、break、exit三者在for循环种的比较
[root@server1 shell]# vim continue.sh
[root@server1 shell]# cat continue.sh
#!/bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ]
then
continue
fi
echo $i
done
echo aaaaaaaaa
[root@server1 shell]# sh continue.sh
1
1
2
2
3
4
4
5
5
aaaaaaaaa
[root@server1 shell]# vim break.sh
[root@server1 shell]# cat break.sh
#!/bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ]
then
break
fi
echo $i
done
echo aaaaaaaaa
[root@server1 shell]# sh break.sh
1
1
2
2
3
aaaaaaaaa
[root@server1 shell]# vim exit.sh
[root@server1 shell]# cat exit.sh
#!/bin/bash
for i in `seq 1 5`
do
echo $i
if [ $i == 3 ]
then
exit
fi
echo $i
done
echo aaaaaaaaa
[root@server1 shell]# sh exit.sh
1
1
2
2
3
(10)函数
[root@server1 shell]# vim fun1.sh
[root@server1 shell]# cat fun1.sh
#!/bin/bash
sum() {
s=$[$1+$2]
echo $s
}
sum 3 5
[root@server1 shell]# sh fun1.sh
8
-------------------------------------------------------------------------
[root@server1 shell]# vim fun2.sh
[root@server1 shell]# cat fun2.sh
#!/bin/bash
ip() {
ifconfig |grep -A1 "$e" |tail -1 |awk '{print $2}' |awk -F':' '{print $2}'
}
read -p "请输入网卡名称:" e
myip=`ip $e`
echo "$e的ip是$myip"
[root@server1 shell]# sh fun2.sh
请输入网卡名称:lo
lo的ip是127.0.0.1
[root@server1 shell]# sh fun2.sh
请输入网卡名称:eth2
eth2的ip是172.25.26.1
注:关系表达式如下:
>:gt <:lt >=:ge <=:le ==:eq !=ne