研究學習 Linux Shell 的系列文章.
這篇文章主要講 正則表達式.
更多
1. 正則表達式
1.1 正則表達式的概念
正則表達式是用於描述字符排列和匹配模式的一種語法規則. 它主要用於字符串的模式分割、匹配、查找及替換操作.
1.2 正則表達式與通配符
- 正則表達式用來在文件中匹配符合條件的字符串,正則是包含匹配。grep、awk、sed 等命令可以支持正則表達式。
- 通配符用來匹配符合條件的文件名,通配符是完全匹配。ls、find、cp 這些命令不支持正則表達式,所以只能使用 shell 自己的通配符來進行匹配了。
- *:匹配任意內容
- ?:匹配任意一個內容
- []:匹配中括號中的一個字符
[root@cloudvm ~]# touch abc.txt adc.txt
[root@cloudvm ~]# ls
abc.txt adc.txt anaconda-ks.cfg
[root@cloudvm ~]# ls a*
abc.txt adc.txt anaconda-ks.cfg
[root@cloudvm ~]# ls a?c.txt
abc.txt adc.txt
[root@cloudvm ~]# ls a[bd]c.txt
abc.txt adc.txt
1.3 基礎正則表達式
正則表達式分爲:
- 基礎正則表達式
- 擴展正則表達式
主要使用基礎正則表達式,擴展正則表達式這裏不介紹
元字符 | 作用 |
---|---|
* |
前一個字符匹配0次或任意多次. |
. |
匹配除了換行符外任意一個字符. |
^ |
匹配行首. 例如:^hello 會匹配以 hello 開頭的行. |
$ |
匹配行尾. 例如:hello& 會匹配以 hello 結尾的行. |
[] |
匹配中括號中指定的任意一個字符,制匹配一個字符. 例如:[aoeiu] 匹配任意一個元音字母,[0-9] 匹配任意一位數字,[a-z][0-9]匹配小寫字和一位數字構成的兩位字符. |
[^] |
匹配除中括號的字符以外的任意一個字符. 例如:[^0-9] 匹配任意一位非數字字符,[^a-z] 表示任意一位非小寫字母. |
\ |
轉義符. 用於取消特殊符號的含義. |
\{n\} |
表示其前面的字符恰好出現 n 次. 例如:[0-9]\{4\} 匹配 4 位數字,[1][3-8][0-9]\{9\} 匹配手機號碼. |
\{n,\} |
表示其前面的字符出現不小於 n 次. 例如:[0-9]\{2,\}表示兩位及以上的數字. |
\{n,m\} |
表示其前面的字符至少出現 n 次,最多出現 m 次. 例如:[a-z]\{6,8\} 匹配6到8位的小寫字母. |
?
和 <>
是擴展正則表達式.
"a*"
# 匹配所有內容,包括空白行
“aa*”
# 匹配至少包含一個a的行
“aaa*”
# 匹配最少包含兩個連續a的字符串
“aaaaa*”
# 匹配最少包含四個連續a的字符串
1.4 幾個例子
1. 匹配日期格式 YYYY-MM-DD
[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}
2. 匹配IP地址
[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\
2. 字符截取命令
2.1 grep 命令
grep
命令用來行提取字符串:
grep [選項] [正則表達式] [文件]
常用選項:
-v
:反匹配,找出不匹配的行-n
:顯示行號-i
:不區分大小寫--color
:[ always | nerver | auto ] 顏色高亮
[root@cloudvm ~]# useradd user1
[root@cloudvm ~]# useradd user2
[root@cloudvm ~]# grep "bin/bash" /etc/passwd
root:x:0:0:root:/root:/bin/bash
lucifer:x:1000:1000::/home/lucifer:/bin/bash
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
[root@cloudvm ~]# grep -n "bin/bash" /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
26:lucifer:x:1000:1000::/home/lucifer:/bin/bash
27:user1:x:1001:1001::/home/user1:/bin/bash
28:user2:x:1002:1002::/home/user2:/bin/bash
[root@cloudvm ~]# grep "bin/bash" /etc/passwd | grep -v "root"
lucifer:x:1000:1000::/home/lucifer:/bin/bash
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
2.2 cut 命令
cut 命令用來列提取字符串:
cut [選項] 文件名
選項:
-f
列號:提取第幾列-d
分隔符:按照指定分隔符分割列
student.txt
文件如下,其中使用製表符
ID Name Gender Mark
1 Ford M 85
2 White M 60
3 Clyde M 70
[root@cloudvm ~]# cut -f 2 student.txt
Name
Ford
White
Clyde
[root@cloudvm ~]# cut -f 2,4 student.txt
Name Mark
Ford 85
White 60
Clyde 70
[root@cloudvm ~]# grep "bin/bash" /etc/passwd | grep -v "root" | cut -f 1 -d ":"
lucifer
user1
user2
缺陷:適合以製表符爲分隔符的文檔,以空格爲分隔符時難以實現需求.
[root@cloudvm ~]# df -h | cut -f 5
Filesystem Size Used Avail Use% Mounted on
devtmpfs 899M 0 899M 0% /dev
tmpfs 910M 0 910M 0% /dev/shm
tmpfs 910M 9.6M 901M 2% /run
tmpfs 910M 0 910M 0% /sys/fs/cgroup
/dev/sda3 19G 1.5G 18G 8% /
/dev/sda1 488M 117M 336M 26% /boot
tmpfs 182M 0 182M 0% /run/user/0
[root@cloudvm ~]# df -h | cut -f 1,3 -d " "
Filesystem
devtmpfs
tmpfs
tmpfs
tmpfs
/dev/sda3
/dev/sda1
tmpfs
2.3 printf 命令
printf '輸出類型輸出格式' 輸出內容
- 輸出類型:
- %ns:輸出字符串. n 是數字指代輸出幾個字符.
- %ni:輸出整數. n 是數字指代輸出幾個數字
- %m.nf:輸出浮點數. m 和 n 是數字,指代輸出的整數位和小數位,如 %8.2f 代表共輸出 8 位數,其中 2 位是小數,6位是整數.
- 輸出格式:
- \a:輸出警告聲音
- \b:輸出退格鍵,也就是 Backspace 鍵
- \f:清除屏幕
- \n:換行
- \r:回車,也就是 Enter 鍵
- \t:水平輸出退格鍵,也就是 Tab 鍵
- \v:垂直輸出退格鍵,也就是 Tab 鍵
[root@cloudvm ~]# printf %s 1 2 3 4 5 6
123456[root@cloudvm ~]#
[root@cloudvm ~]# printf %s %s %s 1 2 3 4 5 6
%s%s123456[root@cloudvm ~]#
[root@cloudvm ~]# printf '%s %s %s' 1 2 3 4 5 6
1 2 34 5 6[root@cloudvm ~]#
[root@cloudvm ~]# printf '%s %s %s\n' 1 2 3 4 5 6
1 2 3
4 5 6
[root@cloudvm ~]# printf '%s' $(cat student.txt)
IDNameGenderMark1FordM852WhiteM603ClydeM70[root@cloudvm ~]#
[root@cloudvm ~]# printf '%s\t%s\t%s\t%s\n' $(cat student.txt)
ID Name Gender Mark
1 Ford M 85
2 White M 60
3 Clyde M 70
在 awk 命令的輸出中支持 print 和 printf 命令
- print:print 會在每個輸出之後自動加入一個換行符(Linux 默認沒有 print 命令)
- printf:printf 是標準格式輸出命令,並不會自動加入換行符,如果需要換行,需要手工加入換行符
2.4 awk 命令
awk '條件1{動作1} 條件2{動作2}...' 文件名
- 條件(Pattern):
- 一般使用關係表達式作爲條件
- x>10 判斷變量x是否大於10
- x>=10 大於等於
- x<=10 小於等於
- 動作(Action):
- 格式化輸出
- 流程控制語句
逐行執行,$n 表示第 n 列. {動作}
前有條件
則條件
成立執行{動作}
,若{動作}
前無條件
則{動作}
直接執行.
[root@cloudvm ~]# awk '{printf $2 "\t" $4 "\n"}' student.txt
Name Mark
Ford 85
White 60
Clyde 70
printf
是標準輸出,print
自帶換行符 \n
.
[root@cloudvm ~]# awk '{print $2 "\t" $4}' student.txt
Name Mark
Ford 85
White 60
Clyde 70
[root@cloudvm ~]# awk '{printf $2 "\t" $4}' student.txt
Name MarkFord 85White 60Clyde 70[root@cloudvm ~]#
[root@cloudvm ~]# df -h | awk '{print $1 "\t" $3}'
Filesystem Used
devtmpfs 0
tmpfs 0
tmpfs 9.6M
tmpfs 0
/dev/sda3 1.5G
/dev/sda1 117M
tmpfs 0
[root@cloudvm ~]# df -h | grep '/dev/sda' | awk '{print $5}'
8%
26%
[root@cloudvm ~]# df -h | grep '/dev/sda' | awk '{print $5}' | cut -d "%" -f 1
8
26
BEGIN 和 END 條件.
[root@cloudvm ~]# awk 'BEGIN{print "test"} {print $2 "\t" $4}' student.txt
test
Name Mark
Ford 85
White 60
Clyde 70
[root@cloudvm ~]# awk 'END{print "test"} {print $2 "\t" $4}' student.txt
Name Mark
Ford 85
White 60
Clyde 70
test
BEGIN 搭配 FS 內置變量設置分隔符,BEGIN 表示在讀取內容之前執行動作
.
[root@cloudvm ~]# cat /etc/passwd | grep /bin/bash | awk '{FS=":"}{print $1 "\t" $3}'
root:x:0:0:root:/root:/bin/bash
lucifer 1000
user1 1001
user2 1002
[root@cloudvm ~]# cat /etc/passwd | grep /bin/bash | awk 'BEGIN{FS=":"}{print $1 "\t" $3}'
root 0
lucifer 1000
user1 1001
user2 1002
關係運算符
[root@cloudvm ~]# cat student.txt | grep -v Name | awk '$4>=70{print $2}'
Ford
Clyde
2.5 sed 命令
sed 是一種幾乎包括所有 UNIX 平臺(包括 Linux)的輕量級流編輯器. sed 主要是用來將數據進行選取、替換、刪除、新增的命令.
sed [選項] ‘[動作]’ 文件名
選項:
- -n:一般 sed 命令會把所有數據都輸出到屏幕,如果加入次選項則只會把經過 sed 命令處理的行輸出到屏幕.
- -e:允許對輸入數據應用多條命令編輯
- -i:用 sed 命令修改結果直接修改讀取數據的文件,而不是由屏幕輸出.
動作:
- a:追加,在當前行後添加一行或多行
- c:行替換,用 c 後面的字符串替換原數據行
- i:插入,在當期行前插入一行或多行.
- d:刪除,刪除指定的行
- p:打印,輸出指定的行.
- s:字串替換,用一個字符串替換另外一個字符串. 格式爲 “行範圍s/舊字串/新字串/g”(和 vim 中的替換格式類似).
[root@cloudvm ~]# sed '2p' student.txt
ID Name Gender Mark
1 Ford M 85
1 Ford M 85
2 White M 60
3 Clyde M 70
[root@cloudvm ~]# sed -n '2p' student.txt
1 Ford M 85
[root@cloudvm ~]# sed '2d' student.txt
ID Name Gender Mark
2 White M 60
3 Clyde M 70
[root@cloudvm ~]# sed '2,4d' student.txt
ID Name Gender Mark
[root@cloudvm ~]# sed '2i test' student.txt
ID Name Gender Mark
test
1 Ford M 85
2 White M 60
3 Clyde M 70
[root@cloudvm ~]# sed '2a test' student.txt
ID Name Gender Mark
1 Ford M 85
test
2 White M 60
3 Clyde M 70
[root@cloudvm ~]# sed '4c Clyde is a fool' student.txt
ID Name Gender Mark
1 Ford M 85
2 White M 60
Clyde is a fool
[root@cloudvm ~]# sed '4s/70/100/g' student.txt
ID Name Gender Mark
1 Ford M 85
2 White M 60
3 Clyde M 100
[root@cloudvm ~]# cat student.txt
ID Name Gender Mark
1 Ford M 85
2 White M 60
3 Clyde M 70
[root@cloudvm ~]# sed -i '4s/70/100/g' student.txt
[root@cloudvm ~]# cat student.txt
ID Name Gender Mark
1 Ford M 85
2 White M 60
3 Clyde M 100
[root@cloudvm ~]# cat student.txt
ID Name Gender Mark
1 Ford M 85
2 White M 60
3 Clyde M 100
[root@cloudvm ~]# sed -e 's/Ford//g;s/White/Green/g' student.txt
ID Name Gender Mark
1 M 85
2 Green M 60
3 Clyde M 100
3. 字符處理命令
3.1 sort 命令
sort [選項] 文件名
選項:
- -f:忽略大小寫
- -n:以數值型進行排序,默認使用字符串型排序
- -r:反向排序
- -t:指定分隔符,默認分隔符是製表符
- -k n[,m]:按照指定的字段範圍排序. 從第 n 字段開始,m 字段結束(默認到行尾)
sort -n -t ":" -k 3,3 /etc/passwd
3.2 wc 命令
wc [選項] 文件
選項:
- -l:只統計行數
- -w:只統計單詞數
- -m:只統級字符數