天天看點

SHELL程式設計小工具本節課程目标一、文本處理工具二、bash的特性

本節課程目标

  • 了解shell中的通配符
  • 熟悉grep、cut、sort等小工具和shell中的通配符的使用

一、文本處理工具

1. ==grep工具==

grep是==行==過濾工具;用于根據關鍵字進行行過濾

文法和選項

文法:

# grep [選項] '關鍵字' 檔案名           

常見選項:

OPTIONS:
    -i: 不區分大小寫
    -v: 查找不包含指定内容的行,反向選擇
    -w: 按單詞搜尋
    -o: 列印比對關鍵字
    -c: 統計比對到的行數
    -n: 顯示行号
    -r: 逐層周遊目錄查找
    -A: 顯示比對行及後面多少行    
    -B: 顯示比對行及前面多少行
    -C: 顯示比對行前後多少行
    -l:隻列出比對的檔案名
    -L:列出不比對的檔案名
    -e: 使用正則比對
    -E:使用擴充正則比對
    ^key:以關鍵字開頭
    key$:以關鍵字結尾
    ^$:比對空行
    --color=auto :可以将找到的關鍵詞部分加上顔色的顯示           

顔色顯示(别名設定):

臨時設定:
# alias grep='grep --color=auto'            //隻針對目前終端和目前使用者生效

永久設定:
1)全局(針對所有使用者生效)
vim /etc/bashrc
alias grep='grep --color=auto'
source /etc/bashrc

2)局部(針對具體的某個使用者)
vim ~/.bashrc
alias grep='grep --color=auto'
source ~/.bashrc           

舉例說明:

==說明:不要直接使用/etc/passwd檔案,将其拷貝到/tmp下做實驗!==

# grep -i root passwd                        忽略大小寫比對包含root的行
# grep -w ftp passwd                         精确比對ftp單詞
# grep -w hello passwd                         精确比對hello單詞;自己添加包含hello的行到檔案
# grep -wo ftp passwd                         列印比對到的關鍵字ftp
# grep -n root passwd                         列印比對到root關鍵字的行好
# grep -ni root passwd                         忽略大小寫比對統計包含關鍵字root的行
# grep -nic root passwd                        忽略大小寫比對統計包含關鍵字root的行數
# grep -i ^root passwd                         忽略大小寫比對以root開頭的行
# grep bash$ passwd                             比對以bash結尾的行
# grep -n ^$ passwd                             比對空行并列印行号
# grep ^# /etc/vsftpd/vsftpd.conf        比對以#号開頭的行
# grep -v ^# /etc/vsftpd/vsftpd.conf    比對不以#号開頭的行
# grep -A 5 mail passwd                      比對包含mail關鍵字及其後5行
# grep -B 5 mail passwd                      比對包含mail關鍵字及其前5行
# grep -C 5 mail passwd                     比對包含mail關鍵字及其前後5行           

2. ==cut工具==

cut是==列==截取工具,用于列的截取

# cut 選項  檔案名           
-c:    以字元為機關進行分割,截取
-d:    自定義分隔符,預設為制表符\t
-f:    與-d一起使用,指定截取哪個區域           

舉例說明:

# cut -d: -f1 1.txt             以:冒号分割,截取第1列内容
# cut -d: -f1,6,7 1.txt     以:冒号分割,截取第1,6,7列内容
# cut -c4 1.txt                 截取檔案中每行第4個字元
# cut -c1-4 1.txt             截取檔案中每行的1-4個字元
# cut -c4-10 1.txt             截取檔案中每行的4-10個字元
# cut -c5- 1.txt                 從第5個字元開始截取後面所有字元           

課堂練習:

用小工具列出你當系統的運作級别。5/3

  1. 如何檢視系統運作級别
    • 指令

      runlevel

    • 檔案

      /etc/inittab

  2. 如何過濾運作級别
runlevel |cut -c3
runlevel | cut -d ' ' -f2
grep -v '^#' /etc/inittab | cut -d: -f2
grep '^id' /etc/inittab |cut -d: -f2
grep "initdefault:$" /etc/inittab | cut -c4
grep -v ^# /etc/inittab |cut -c4
grep 'id:' /etc/inittab |cut -d: -f2
cut -d':' -f2 /etc/inittab |grep -v ^#
cut -c4 /etc/inittab |tail -1
cut -d: -f2 /etc/inittab |tail -1           

3. sort工具

sort工具用于排序;它将檔案的每一行作為一個機關,從首字元向後,依次按ASCII碼值進行比較,最後将他們按升序輸出。

-u :去除重複行
-r :降序排列,預設是升序
-o : 将排序結果輸出到檔案中,類似重定向符号>
-n :以數字排序,預設是按字元排序
-t :分隔符
-k :第N列
-b :忽略前導空格。
-R :随機排序,每次運作的結果均不同           

舉例說明

# sort -n -t: -k3 1.txt             按照使用者的uid進行升序排列
# sort -nr -t: -k3 1.txt             按照使用者的uid進行降序排列
# sort -n 2.txt                         按照數字排序
# sort -nu 2.txt                         按照數字排序并且去重
# sort -nr 2.txt 
# sort -nru 2.txt 
# sort -nru 2.txt 
# sort -n 2.txt -o 3.txt             按照數字排序并将結果重定向到檔案
# sort -R 2.txt 
# sort -u 2.txt            

4.uniq工具

uniq用于去除==連續==的==重複==行
常見選項:
-i: 忽略大小寫
-c: 統計重複行次數
-d:隻顯示重複行

舉例說明:
# uniq 2.txt 
# uniq -d 2.txt 
# uniq -dc 2.txt            

5.tee工具

tee工具是從标準輸入讀取并寫入到标準輸出和檔案,即:雙向覆寫重定向(螢幕輸出|文本輸入)
選項:
-a 雙向追加重定向

# echo hello world
# echo hello world|tee file1
# cat file1 
# echo 999|tee -a file1
# cat file1            

6.diff工具

diff工具用于逐行比較檔案的不同

注意:diff描述兩個檔案不同的方式是告訴我們==怎樣改變第一個==檔案之後==與第二個檔案比對==。

diff [選項] 檔案1 檔案2           

常用選項:

選項 含義 備注
-b 不檢查空格
-B 不檢查空白行
-i 不檢查大小寫
-w 忽略所有的空格
--normal 正常格式顯示(預設)
-c 上下文格式顯示
-u 合并格式顯示
  • 比較兩個==普通檔案==異同,檔案準備:
[root@MissHou ~]# cat file1
aaaa
111
hello world
222
333
bbb
[root@MissHou ~]#
[root@MissHou ~]# cat file2
aaa
hello
111
222
bbb
333
world           

1)正常顯示

diff目的:file1如何改變才能和file2比對
[root@MissHou ~]# diff file1 file2
1c1,2                    第一個檔案的第1行需要改變(c=change)才能和第二個檔案的第1到2行比對            
< aaaa                小于号"<"表示左邊檔案(file1)檔案内容
---                    ---表示分隔符
> aaa                    大于号">"表示右邊檔案(file2)檔案内容
> hello
3d3                    第一個檔案的第3行删除(d=delete)後才能和第二個檔案的第3行比對
< hello world
5d4                    第一個檔案的第5行删除後才能和第二個檔案的第4行比對
< 333
6a6,7                    第一個檔案的第6行增加(a=add)内容後才能和第二個檔案的第6到7行比對
> 333                    需要增加的内容在第二個檔案裡是333和world
> world           

2)上下文格式顯示

[root@MissHou ~]# diff -c file1 file2
前兩行主要列出需要比較的檔案名和檔案的時間戳;檔案名前面的符号***表示file1,---表示file2
*** file1       2019-04-16 16:26:05.748650262 +0800
--- file2       2019-04-16 16:26:30.470646030 +0800
***************    我是分隔符
*** 1,6 ****        以***開頭表示file1檔案,1,6表示1到6行
! aaaa                !表示該行需要修改才與第二個檔案比對
  111
- hello world        -表示需要删除該行才與第二個檔案比對
  222
- 333                    -表示需要删除該行才與第二個檔案比對
  bbb
--- 1,7 ----        以---開頭表示file2檔案,1,7表示1到7行
! aaa                    表示第一個檔案需要修改才與第二個檔案比對
! hello                表示第一個檔案需要修改才與第二個檔案比對
  111
  222
  bbb
+ 333                    表示第一個檔案需要加上該行才與第二個檔案比對
+ world                表示第一個檔案需要加上該行才與第二個檔案比對
           

3)合并格式顯示

[root@MissHou ~]# diff -u file1 file2
前兩行主要列出需要比較的檔案名和檔案的時間戳;檔案名前面的符号---表示file1,+++表示file2
--- file1       2019-04-16 16:26:05.748650262 +0800
+++ file2       2019-04-16 16:26:30.470646030 +0800
@@ -1,6 +1,7 @@
-aaaa
+aaa
+hello
 111
-hello world
 222
-333
 bbb
+333
+world           
  • 比較兩個==目錄不同==
預設情況下也會比較兩個目錄裡相同檔案的内容
[root@MissHou  tmp]# diff dir1 dir2
diff dir1/file1 dir2/file1
0a1
> hello
Only in dir1: file3
Only in dir2: test1
如果隻需要比較兩個目錄裡檔案的不同,不需要進一步比較檔案内容,需要加-q選項
[root@MissHou  tmp]# diff -q dir1 dir2
Files dir1/file1 and dir2/file1 differ
Only in dir1: file3
Only in dir2: test1
           

其他小技巧:

有時候我們需要以一個檔案為标準,去修改其他檔案,并且修改的地方較多時,我們可以通過打更新檔的方式完成。

1)先找出檔案不同,然後輸出到一個檔案
[root@MissHou ~]# diff -uN file1 file2 > file.patch
-u:上下文模式
-N:将不存在的檔案當作空檔案
2)将不同内容打更新檔到檔案
[root@MissHou ~]# patch file1 file.patch
patching file file1
3)測試驗證
[root@MissHou ~]# diff file1 file2
[root@MissHou ~]#
           

7. paste工具

paste工具用于合并檔案行
常用選項:
-d:自定義間隔符,預設是tab
-s:串行處理,非并行           

8. tr工具

tr用于字元轉換,替換和删除;主要用于==删除檔案中控制字元==或進行==字元轉換==

用法1:指令的執行結果交給tr處理,其中string1用于查詢,string2用于轉換處理

 commands|tr  'string1'  'string2'

用法2:tr處理的内容來自檔案,記住要使用"<"标準輸入

 tr  'string1'  'string2' < filename

用法3:比對string1進行相應操作,如删除操作

 tr [options] 'string1' < filename           
-d 删除字元串1中所有輸入字元。
-s 删除所有重複出現字元序列,隻保留第一個;即将重複出現字元串壓縮為一個字元串           

常比對字元串:

字元串
==a-z==或[:lower:] 比對所有小寫字母 所有大小寫和數字[a-zA-Z0-9]
==A-Z==或[:upper:] 比對所有大寫字母
==0-9==或[:digit:] 比對所有數字
[:alnum:] 比對所有字母和數字
[:alpha:] 比對所有字母
[:blank:] 所有水準空白
[:punct:] 比對所有标點符号
[:space:] 所有水準或垂直的空格
[:cntrl:] 所有控制字元 \f Ctrl-L 走行換頁<br/>\n Ctrl-J 換行

\r Ctrl-M 回車

\t Ctrl-I tab鍵 |

[root@MissHou  shell01]# cat 3.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
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
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
boss02:x:516:511::/home/boss02:/bin/bash
vip:x:517:517::/home/vip:/bin/bash
stu1:x:518:518::/home/stu1:/bin/bash
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
aaaaaaaaaaaaaaaaaaaa
bbbbbb111111122222222222233333333cccccccc
hello world 888
666
777
999


# tr -d '[:/]' < 3.txt                 删除檔案中的:和/
# cat 3.txt |tr -d '[:/]'            删除檔案中的:和/
# tr '[0-9]' '@' < 3.txt             将檔案中的數字替換為@符号
# tr '[a-z]' '[A-Z]' < 3.txt         将檔案中的小寫字母替換成大寫字母
# tr -s '[a-z]' < 3.txt             比對小寫字母并将重複的壓縮為一個
# tr -s '[a-z0-9]' < 3.txt         比對小寫字母和數字并将重複的壓縮為一個
# tr -d '[:digit:]' < 3.txt         删除檔案中的數字
# tr -d '[:blank:]' < 3.txt         删除水準空白
# tr -d '[:space:]' < 3.txt         删除所有水準和垂直空白
           

小試牛刀

  1. 使用小工具分别截取目前主機IP;截取NETMASK;截取廣播位址;截取MAC位址
# ifconfig eth0|grep 'Bcast'|tr -d '[a-zA-Z ]'|cut -d: -f2,3,4
10.1.1.1:10.1.1.255:255.255.255.0
# ifconfig eth0|grep 'Bcast'|tr -d '[a-zA-Z ]'|cut -d: -f2,3,4|tr ':' '\n'
10.1.1.1
10.1.1.255
255.255.255.0
# ifconfig eth0|grep 'HWaddr'|cut -d: -f2-|cut -d' ' -f4
00:0C:29:25:AE:54
# ifconfig eth0|grep 'HW'|tr -s ' '|cut -d' ' -f5
00:0C:29:B4:9E:4E

# ifconfig eth1|grep Bcast|cut -d: -f2|cut -d' ' -f1
# ifconfig eth1|grep Bcast|cut -d: -f2|tr -d '[ a-zA-Z]'
# ifconfig eth1|grep Bcast|tr -d '[:a-zA-Z]'|tr ' ' '@'|tr -s '@'|tr '@' '\n'|grep -v ^$
# ifconfig eth0|grep 'Bcast'|tr -d [:alpha:]|tr '[ :]' '\n'|grep -v ^$
# ifconfig eth1|grep HWaddr|cut -d ' ' -f11
# ifconfig eth0|grep HWaddr|tr -s ' '|cut -d' ' -f5
# ifconfig eth1|grep HWaddr|tr -s ' '|cut -d' ' -f5
# ifconfig eth0|grep 'Bcast'|tr -d 'a-zA-Z:'|tr ' ' '\n'|grep -v '^$'           
  1. 将系統中所有普通使用者的使用者名、密碼和預設shell儲存到一個檔案中,要求使用者名密碼和預設shell之間用tab鍵分割
# grep 'bash$' passwd |grep -v 'root'|cut -d: -f1,2,7|tr ':' '\t' |tee abc.txt           

二、bash的特性

1、指令和檔案自動補全

Tab隻能補全==指令和檔案== (RHEL6/Centos6)

2、常見的快捷鍵

^c               終止前台運作的程式
^z                  将前台運作的程式挂起到背景
^d               退出 等價exit
^l               清屏 
^a |home      光标移到指令行的最前端
^e |end      光标移到指令行的後端
^u               删除光标前所有字元
^k               删除光标後所有字元
^r                 搜尋曆史指令           

3 、==常用的通配符(重點)==

*:    比對0或多個任意字元
?:    比對任意單個字元
[list]:    比對[list]中的任意單個字元,或者一組單個字元   [a-z]
[!list]: 比對除list中的任意單個字元
{string1,string2,...}:比對string1,string2或更多字元串


# rm -f file*
# cp *.conf  /dir1
# touch file{1..5}           

4、==bash中的引号(重點)==

  • 雙引号"" :會把引号的内容當成整體來看待,允許通過$符号引用其他變量值
  • 單引号'' :會把引号的内容當成整體來看待,禁止引用其他變量值,shell中特殊符号都被視為普通字元
  • 反撇号`` :反撇号和$()一樣,引号或括号裡的指令會優先執行,如果存在嵌套,反撇号不能用
[root@MissHou  dir1]# echo "$(hostname)"
server
[root@MissHou  dir1]# echo '$(hostname)'
$(hostname)
[root@MissHou  dir1]# echo "hello world"
hello world
[root@MissHou  dir1]# echo 'hello world'
hello world

[root@MissHou  dir1]# echo $(date +%F)
2018-11-22
[root@MissHou  dir1]# echo `echo $(date +%F)`
2018-11-22
[root@MissHou  dir1]# echo `date +%F`
2018-11-22
[root@MissHou  dir1]# echo `echo `date +%F``
date +%F
[root@MissHou  dir1]# echo $(echo `date +%F`)
2018-11-22