1. 程式人生 > >shell編程初步、grep及正則表達式

shell編程初步、grep及正則表達式

Linux shell 正則表達式

bash的基礎特性(3)
1、提供了編程環境

程序=指令+數據

程序編程風格
過程式:以指令為中心,數據服務於指令
對象式:以數據為中心,指令服務於數據

shell程序:提供了編程能力,解釋執行

程序的執行方式:
計算機:運行二進制指令
編程語言:
低級:匯編
高級:
編譯:高級語言-->編譯器-->目標代碼(C、C++、java)
解釋:高級語言-->解釋器-->機器代碼(shell、perl、python)

過程式編程:
順序執行、循環執行、選擇執行

shell編程:過程式、解釋執行
編程語言的基本結構:數據存儲(變量、數組)、表達式、語句

shell腳本:文本文件
shebang:
#!/bin/bash

#!/usr/bin/python
#!/usr/bin/perl

magic number 魔數

運行腳本:
1、給予執行權限,通過具體的文件路徑指定文件執行
2、直接運行解釋器,將腳本作為解釋器程序的參數運行

變量:命名的內存空間

數據存儲方式:ASCII
字符:110 轉換為二進制 24位
數值:110 轉換為二進制 8位(整型、浮點型)

變量的作用:
1、數據存儲格式;2、參與的運算、3、表示的數據範圍

類型:
字符
數值:整型、浮點型

編程程序語言:
強類型:C
弱類型:bash 把所有要存儲的數據統統當作字符進行,支持隱式類型轉換、不支持浮點數

邏輯運算:
true、false(1、0)

與:
1 && 1=1
1 && 0=0
0 && 1=0
0 && 0=0

或:
1 || 1=1
1 || 0=1
0 || 1=1
0 || 0=0

非:
!1=0
!0=1

短路運算:
與:
第一個為0,結果必定為0
[root@localhost ~]# catt /etc/issue && cat /etc/issue
-bash: catt: command not found

    [root@localhost ~]# catt /etc/issue && cat /etc/issuee
    -bash: catt: command not found

    第一個為1,第二個必須要參與運算
    [root@localhost ~]# cat /etc/issue && echo "true"
    CentOS release 6.5 (Final)
    Kernel \r on an \m

    true

    [root@localhost ~]# cat /etc/issue && catt /etc/issue
    CentOS release 6.5 (Final)
    Kernel \r on an \m

    -bash: catt: command not found

或:
    第一個為1,結果必定為1
    [root@localhost ~]# cat /etc/issue || cat /etc/issue
    CentOS release 6.5 (Final)
    Kernel \r on an \m

    [root@localhost ~]# cat /etc/issue || catt /etc/issue
    CentOS release 6.5 (Final)
    Kernel \r on an \m

    第一個為0,第二個必須要參與運算
    [root@localhost ~]# catt /etc/issue || cat /etc/issue
    -bash: catt: command not found
    CentOS release 6.5 (Final)
    Kernel \r on an \m

    [root@localhost ~]# catt /etc/issue || cat /etc/issuee
    -bash: catt: command not found
    cat: /etc/issuee: No such file or directory

與、或的混合應用
[root@localhost ~]# cat /etc/issue &> /dev/null && echo "true" || echo "false"
true

[root@localhost ~]# catt /etc/issue &> /dev/null && echo "true" || echo "false"
false

grep:
linux上文本處理的三劍客
grep 文本過濾工具(模式:pattern)
grep、egrep、fgrep
sed stream editor 流編輯器 文本編輯工具
awk linux上的實現gawk 文本報告生成器

grep:global search expression and print out the line.
作用:文本搜索工具,根據用戶指定的"模式"對目標文本逐行進行匹配檢查,打印匹配到的行;
模式:由正則表達式字符及文本字符所編寫的過濾條件

REGEXP:由一類特殊字符及文本字符所編寫的模式,其中有些字符不表示字符字面意義,而表示控制或通配的功能;
分兩類:
基本正則表達式:BRE
擴展正則表達式:ERE
    grep -E,egrep

正則表達式引擎
grep [options] pattern [file...]
選項:
--color=auto,對匹配到的文本著色顯示
[root@localhost ~]# grep --color=auto "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

-v:顯示不能夠被pattern匹配到的行
[root@localhost ~]# grep -v "abc" /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m

-i:忽略字符大小寫
[root@localhost ~]# grep -i "centos" /etc/issue
CentOS release 6.5 (Final)

-o:僅顯示匹配到的字符串
[root@localhost ~]# grep -o "release" /etc/issue
release

-q:靜默模式,不輸出任何信息
[root@localhost ~]# grep -q "release" /etc/issue
[root@localhost ~]# echo $?
0

-A #:顯示匹配到的行,追加顯示後面的#行,如果後面沒有文本內容,則不予顯示,表示after
[root@localhost ~]# grep -A 2 "root" /etc/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

operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

-B #:顯示匹配到的行,追加顯示前面的#行,如果前面沒有文本內容,則不予顯示,表示before
[root@localhost ~]# grep -B 2 "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

-C #:顯示匹配到的行,追加顯示前後的各#行,如果前後沒有文本內容,則不予顯示,表示context上下文
[root@localhost ~]# grep -C 2 "root" /etc/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

mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

-E:使用ERE擴展正則表達式

基本正則表達式
字符匹配:
.:匹配任意單個字符
[root@localhost ~]# grep "." /tmp/abc
a
b
c

[]:匹配指定範圍內的任意單個字符
[root@localhost ~]# grep [abc] /tmp/abc
a
b
c

[^]:匹配指定範圍外的任意單個字符
[root@localhost ~]# grep [^abc] /tmp/abc
d
e

[:digit:]:匹配任意單個數字
[root@localhost ~]# grep [[:digit:]] /tmp/abc
1
2
3

[:lower:]:匹配任意單個小寫字母
[root@localhost ~]# grep [[:lower:]] /tmp/abc
a
b
c

[:upper:]:匹配任意單個大寫字母
[root@localhost ~]# grep [[:upper:]] /tmp/abc
A
B
C

[:alpha:]:匹配任意單個大小寫字母
[root@localhost ~]# grep [[:alpha:]] /tmp/abc
a
b
c
A
B
C

[:alnum:]:匹配任意單個大小寫字母或數字
[root@localhost ~]# grep [[:alnum:]] /tmp/abc
a
b
c
1
2
3
A
B
C

[:punct:]:匹配任意單個標點符號
[root@localhost ~]# grep [[:punct:]] /tmp/abc
,
.
?

[:space:]:匹配空格

匹配次數:用在要指定次數的字符後面,用於指定前面的的字符要出現的次數
:匹配前面的字符任意次,盡可能的匹配,貪婪模式
[root@localhost ~]# grep "a
b" /tmp/abc
b
b
ab
aab
aaab

.:任意長度的任意字符
[root@localhost ~]# grep ".
" /tmp/abc
a
b
c

\?:匹配其前面的字符0或1次,即前面的字符可有可無
[root@localhost ~]# grep --color=auto "a\?b" /tmp/abc
b
b
ab
aab
aaab
xyab
xyxyab
xyxyxyab

+:匹配其前面的字符至少1次;
[root@localhost ~]# grep "a+b" /tmp/abc
ab
aab
aaab

{m}:匹配前面的字符m次
[root@localhost ~]# grep "a{3}b" /tmp/abc
aaab

{m,n}:匹配前面的字符至少m次,至多n次
[root@localhost ~]# grep "a{1,3}b" /tmp/abc
ab
aab
aaab

{0,n}:匹配前面的字符至多n次
[root@localhost ~]# grep "a{0,3}b" /tmp/abc
b
b
ab
aab
aaab

{m,}:匹配前面的字符至少m次
[root@localhost ~]# grep "a{2,}b" /tmp/abc
aab
aaab

位置錨定:
^:行首錨定,用於模式的最左側
[root@localhost ~]# grep "^root" /etc/passwd
root:x:0:0:root:/root:/bin/bash

$:行尾錨定,用於模式的最右側
[root@localhost ~]# grep "bash$" /etc/passwd
root:x:0:0:root:/root:/bin/bash
mary:x:503:503:I am mary.:/home/mary:/bin/bash
centos:x:504:504::/tmp/centos:/bin/bash
test:x:505:505::/tmp/test:/bin/bash
rocket:x:507:507::/home/rocket:/bin/bash

^pattern$:用戶模式匹配整行
[root@localhost ~]# grep "^ab$" /tmp/abc
ab

^$:匹配空行

\<或\b:詞首錨定,用於單詞模式的左側
[root@localhost ~]# grep "\<root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

\>或\b:詞尾錨定,用於單詞模式的右側
[root@localhost ~]# grep "bash\>" /etc/passwd
root:x:0:0:root:/root:/bin/bash
mary:x:503:503:I am mary.:/home/mary:/bin/bash
centos:x:504:504::/tmp/centos:/bin/bash
test:x:505:505::/tmp/test:/bin/bash
rocket:x:507:507::/home/rocket:/bin/bash

\<pattern\>:匹配整個單詞
[root@localhost ~]# grep "\<aaab\>" /tmp/abc
aaab

分組:
():將一個或多個字符捆綁在一起,當作一個整體進行處理
[root@localhost ~]# grep --color=auto "(xy)*ab" /tmp/abc
ab
aab
aaab
xyab
xyxyab
xyxyxyab

註意:分組括號中的模式匹配到的內容會被正則表達式引擎記錄與內部的變量中,這些變量的命名方式為:\1,\2,\3...
\1:從左側器,第一個左括號以及匹配右括號之間的模式所匹配到的字符
(ab+(xy))
\1:ab+(xy)

\2:xy

後向引用:引用前面的分組括號中到的模式所匹配的字符,(而非模式本身)
[root@localhost ~]# grep --color=auto "(xy)*ab\1+" /tmp/abc
xyabxy
xyxyabxyxy
xyxyxyabxyxyxy

練習:
1、顯示/proc/meminfo文件中以大小s開頭的行(要求:使用兩種方式)
grep "^[sS]" /proc/meminfo
grep -i "^s" /proc/meminfo

2、顯示/etc/passwd文件中不以/bin/bash結尾的行;
grep -v "/bin/bash$" /etc/passwd

3、顯示/etc/passwd文件中ID號最大的用戶的用戶名;
cat /etc/passwd | sort -t: -k3 -n | tail -1 | cut -d: -f1

4、如果用戶root存在,顯示其默認的shell程序;
cat /etc/passwd | sort -t: -k3 -n | tail -1 | cut -d: -f1
sort -t: -k3 -n /etc/passwd | tail -1 | cut -d: -f1

5、找出/etc/passwd中的兩位或三位數;
id root &> /dev/null && grep "^root\>" /etc/passwd | cut -d: -f7
grep "^root\>" /etc/passwd &> /dev/null && grep "^root\>" /etc/passwd | cut -d: -f7

6、顯示/etc/rc.d/rc.sysinit文件中,至少以一個空白字符開頭的且後面存在非空白字符的行;
grep "^[[:space:]]+[^[:space:]]" /etc/rc.d/rc.sysinit

7、找出"netstat -tan"命令的結果中以"LISTEN"後跟0、1或多個空白字符結尾的行;
netstat -tan | grep "LISTEN([[:space:]])$"
netstat -tan | grep "LISTEN[[:space:]]
$"

8、添加用戶bash、testbash、basher以及nologin(其shell為/sbin/nologin);而後找出/etc/passwd文件中同shell名的行;
useradd bash
useradd testbash
useradd basher
useradd -s /sbin/nologin nologin

[root@localhost ~]# tail -4 /etc/passwd
bash:x:601:601::/home/bash:/bin/bash
testbash:x:602:602::/home/testbash:/bin/bash
basher:x:603:603::/home/basher:/bin/bash
nologin:x:604:604::/home/nologin:/sbin/nologin

grep "\([[:alnum:]]\+\).*\1\?" /etc/passwd 錯誤做法
grep "^\([[:alnum:]]\{1,\}\>\).*\1$" /etc/passwd
grep "^\([[:alnum:]]\{1,\}\)\>.*\1$" /etc/passwd
grep "\(\<[[:alnum:]]\{1,\}\>\).*\1$" /etc/passwd
grep "\(\<[[:alnum:]]\+\>\).*\1$" /etc/passwd

練習:
1、寫一個腳本,實現如下功能
如果user1用戶存在,就顯示其存在,否則添加之;
顯示添加的用戶的id號等信息
[root@localhost test]# cat /tmp/test/a.sh
[root@localhost test]# cat /tmp/test/a.sh
#!/bin/bash

id user1 &> /dev/null && echo "user1 exists." || useradd user1

grep "\<user1\>" /etc/passwd
id user1

[root@localhost test]# bash /tmp/test/a.sh
user1:x:605:605::/home/user1:/bin/bash
uid=605(user1) gid=605(user1) groups=605(user1)

[root@localhost test]# bash /tmp/test/a.sh
user1 exists.
user1:x:605:605::/home/user1:/bin/bash
uid=605(user1) gid=605(user1) groups=605(user1)

2、寫一個腳本,完成如下功能
如果root用戶登錄了當前系統,就顯示root用戶在線,否則說明其未登錄
[root@localhost test]# cat /tmp/test/b.sh
#!/bin/bash

who | grep "^root\>" &> /dev/null && echo "user online." || "user no login."

[root@localhost test]# bash /tmp/test/b.sh
user online.

shell編程初步、grep及正則表達式