【Linux】【Shell】Shell 正則表達式

研究學習 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:只統級字符數
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章