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