文章目錄
- 1.初識sed命令
- 1.1 sed命令是什麼
- 1.2 sed工作原理
- 1.3 sed 命令怎麼用
- 1.4 示例
- 1.4.1 sed的n選項和編輯命令p的示例
- 1.4.2 sed的d編輯命令(不刪除原文件內容)示例
- 1.4.3 sed的編輯命令之a追加命令示例
- 1.4.4 sed的編輯命令之i插入命令示例
- 1.4.5 sed的編輯命令之c替換命令示例
- 1.4.6 sed的編輯命令之r讀入命令示例
- 1.4.7 sed的編輯命令之w寫入命令示例(w命令不加-i也是直接修改原文件!)
- 1.4.8 sed的編輯命令之替換s命令示例
- 1.5 sed的s編輯命令可以使用任意分隔符作爲定界符
- 1.6 sed 命令的-i 選項
- 1.7 sed的編輯命令補充之:G命令
- 1.8 sed命令特殊用法
- 1.9 sed的s命令中支持\t \n \s(正則裏表示空白)
- 2 練習
shell中最核心的三個命令grep、sed、awk。
其中,
grep:文本搜索。
sed:文本處理。
awk:文本分析工具、語言。
本文主要講述sed命令的用法
1.初識sed命令
1.1 sed命令是什麼
sed是一種支持正則表達式的非交互式流編輯器。是腳本中修改文本或者文本替換的最佳工具。
1.2 sed工作原理
sed工作在內存,有兩個空間:
- pattern space(模式空間):緩存空間,較多使用(模式空間裏處理一行內容後,會將這一行內容刪除。加載第2行內容);
- hold space(保留空間):臨時倉庫,很少使用。
工作原理:
sed編輯器逐行處理文件,並將輸出結果打印到屏幕上。sed命令將當前處理的行讀入模式空間(pattern space)進行處理。sed在該行上執行完所有的命令後就將處理好的行打印到屏幕上(除非之前的命令刪除了該行),sed處理完一行就將其從模式空間裏刪除,然後將下一行讀入模式空間進行處理、顯示。處理完文件的最後一行,sed便會結束運行。sed在臨時緩衝區(模式空間)對文件進行處理,所以不會修改原文件,除非顯示指明 -i 選項。
1.3 sed 命令怎麼用
sed的常用語法命令格式:
sed [選項] sed編輯命令 輸入文件
其他shell命令 | sed [選項] sed編輯命令
sed [選項] 輸入文件
sed的常用選項:
- n:只顯示匹配處理的行(否則會輸出所有)
- e:執行多個編輯命令時(一般用;代替)
- i:直接在文件中進行修改,而不是輸出到屏幕(此時不要接-n或-p命令,會導致源文件出問題)
- r:支持擴展正則表達式
- f:從腳本文件中讀取內容並執行(文件中的編輯命令每行一個,不用;隔開)
sed的常用編輯命令:
- p:打印匹配行 print
- d:刪除指定行 delete
- a:在匹配行後面追加 append
- i:在匹配行前面插入 insert
- c:整行替換
- r:將文件的內容讀入 read
- w:將文本寫入文件 write
- s:字符串替換(匹配正則表達式)substitution
sed裏單引號和雙引號的作用區別:
- 雙引號裏可以使用shell裏的變量;單引號不能。
- 單引號和雙引號裏都可以存放模式。
1.4 示例
1.4.1 sed的n選項和編輯命令p的示例
PS:文件sed.txt只有17行數據,每行內容分別爲1,2,3,4…17。
顯示文件的第1、2行:
[root@liupeng lp]# sed -n '1,2p' sed.txt
1
2
[root@liupeng lp]#
或:
[root@liupeng lp]# sed -n '3,$!p' sed.txt -->即不顯示從第3行到最後一行
1
2
[root@liupeng lp]#
顯示文件的第2至5行:
[root@liupeng lp]# sed -n '2,5p' sed.txt
2
3
4
5
[root@liupeng lp]#
或:
[root@liupeng lp]# sed -n '2,+3p' sed.txt
2
3
4
5
[root@liupeng lp]#
顯示文件的第10行:
[root@liupeng lp]# sed -n '10p' sed.txt
10
[root@liupeng lp]#
顯示文件的最後一行:
[root@liupeng lp]# sed -n '$p' sed.txt
17
[root@liupeng lp]#
顯示文件的1,3,5行:
[root@liupeng lp]# sed -n '1p;3p;5p' sed.txt -->注意此處變爲了分號!
1
3
5
[root@liupeng lp]#
顯示單數行:
[root@liupeng lp]# sed -n '1~2p' sed.txt --> ~表示步長
1
3
5
7
9
11
13
15
17
[root@liupeng lp]#
顯示偶數行:
[root@liupeng lp]# sed -n '0~2p' sed.txt
2
4
6
8
10
12
14
16
[root@liupeng lp]#
加入模式:
這裏的模式可以是正則表達式也可以是精確字符,
模式用/括起,擴展正則要加 -r選項。
sed -n '/模式/p’ 輸入文件
顯示包含2的行:
[root@liupeng lp]# sed -n '/2/p' sed.txt
2
12
[root@liupeng lp]#
不顯示1開頭的行:
[root@liupeng lp]# sed -rn '/^1/!p' sed.txt
2
3
4
5
6
7
8
9
[root@liupeng lp]#
顯示以2爲結尾的行:
[root@liupeng lp]# sed -n '/2$/p' sed.txt
2
12
[root@liupeng lp]#
顯示以1和3開頭的行:
[root@liupeng lp]# sed -n '/^[1,3]/p' sed.txt
1
3
10
11
12
13
14
15
16
17
[root@liupeng lp]#
1.4.2 sed的d編輯命令(不刪除原文件內容)示例
刪除操作可以根據行號和模式匹配進行操作。
刪除1-15行:
[root@liupeng lp]# sed '1,15d' sed.txt
16
17
[root@liupeng lp]#
刪除包含數字1的行:
[root@liupeng lp]# sed '/1/d' sed.txt
2
3
4
5
6
7
8
9
[root@liupeng lp]#
除了包含數字1的行都刪除:
[root@liupeng lp]# sed '/1/!d' sed.txt
1
10
11
12
13
14
15
16
17
[root@liupeng lp]#
刪除空行和註釋:
[root@liupeng lp]# sed -r '/^$|^#/d' sed.txt -->^$指空行;^# 以#開頭的行,即註釋行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@liupeng lp]#
刪除空行再刪除註釋行:
[root@liupeng lp]# sed -e '/^$/d' -e '/^#/d' sed.txt -->第二個-e用分號代替也可以
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@liupeng lp]#
1.4.3 sed的編輯命令之a追加命令示例
追加操作可以根據行號和模式匹配進行操作 (不更改原文件)。
新建一個sed2.txt文件,內容爲數字1~7。
[root@liupeng lp]# cat sed2.txt
1
2
3
4
5
6
7
[root@liupeng lp]#
在第一行後面追加字符串abcabc:
[root@liupeng lp]# sed '1a abcabc' sed2.txt
1
abcabc
2
3
4
5
6
7
[root@liupeng lp]#
在包含數字2的行下面追加字符串bcbcbc:
[root@liupeng lp]# sed '/2/a bcbcbc' sed2.txt
1
2
bcbcbc
3
4
5
6
7
[root@liupeng lp]#
1.4.4 sed的編輯命令之i插入命令示例
插入操作可以根據行號和模式匹配進行操作 。
在最後一行的前面插入字符串bcbcbc:
[root@liupeng lp]# sed '$i bcbcbc' sed2.txt
1
2
3
4
5
6
bcbcbc
7
[root@liupeng lp]#
在包含數字3的行前面插入字符串bcbcbc:
[root@liupeng lp]# sed '/3/i bcbcbc' sed2.txt
1
2
bcbcbc
3
4
5
6
7
[root@liupeng lp]#
1.4.5 sed的編輯命令之c替換命令示例
更改整行操作可以根據行號和模式匹配進行操作。
將數字2所在的行替換成字符串bcbcbc:
[root@liupeng lp]# sed '/2/c bcbcbc' sed2.txt
1
bcbcbc
3
4
5
6
7
[root@liupeng lp]#
將第三行替換成字符串bcbcbc:
[root@liupeng lp]# sed '3c bcbcbc' sed2.txt
1
2
bcbcbc
4
5
6
7
[root@liupeng lp]#
1.4.6 sed的編輯命令之r讀入命令示例
讀入操作可以根據行號和模式匹配進行操作。
在sed2.txt文件的末尾後面讀入/etc/passwd文件的所有內容:
[root@liupeng lp]# sed '$r /etc/passwd' sed2.txt
1
2
3
4
5
6
7
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@liupeng lp]#
在/dev/sda1後面讀入sed2.txt文件的內容:
[root@liupeng lp]# df -h | sed '/dev\/sda1/r sed2.txt'
文件系統 容量 已用 可用 已用%% 掛載點
/dev/mapper/vg_liupeng-lv_root
18G 13G 4.2G 75% /
tmpfs 491M 88K 491M 1% /dev/shm
/dev/sda1 485M 33M 427M 8% /boot
1
2
3
4
5
6
7
[root@liupeng lp]#
1.4.7 sed的編輯命令之w寫入命令示例(w命令不加-i也是直接修改原文件!)
寫入文件操作可以根據行號和模式匹配進行操作。
將文件/etc/passwd的第一行寫到sed2.txt(和r讀入命令順序正好相反):
[root@liupeng lp]# sed '1w sed2.txt' /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
......
[root@liupeng lp]# cat sed2.txt
root:x:0:0:root:/root:/bin/bash
[root@liupeng lp]#
將文件/etc/inittab所有不是#開頭的行都寫入sed2.txt:
[root@liupeng lp]# sed '/^#/!w sed2.txt' /etc/inittab
# inittab is only used by upstart for the default runlevel.
#
# ADDING OTHER CONFIGURATION HERE WILL HAVE NO EFFECT ON YOUR SYSTEM.
#
# System initialization is started by /etc/init/rcS.conf
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Ctrl-Alt-Delete is handled by /etc/init/control-alt-delete.conf
#
# Terminal gettys are handled by /etc/init/tty.conf and /etc/init/serial.conf,
# with configuration in /etc/sysconfig/init.
#
# For information on how to write upstart event handlers, or how
# upstart works, see init(5), init(8), and initctl(8).
#
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:5:initdefault:
[root@liupeng lp]# cat sed2.txt
id:5:initdefault:
[root@liupeng lp]#
1.4.8 sed的編輯命令之替換s命令示例
sed -n [行號或模式]s/查找內容/替換內容/[替換標記] 文件
替換操作可以根據行號和模式匹配進行操作。
新建一個sed2.txt文件,內容如下:
[root@liupeng lp]# cat sed2.txt
1 1 1
2 2 2
3 3 3
22 2 222
4 4 4
5 5 5
6 6 6
7 7 7
[root@liupeng lp]#
替換標記有四種:
數字:替換每行的第幾個。
- g:全局替換,否則只替換第一個字符串。
- p:顯示被執行替換操作的行,與-n合用。
- w:將執行替換操作的行輸出到指定文件。
示例:
將sed2.txt中每行的第二個數字2替換成bb:
[root@liupeng lp]# sed -n 's/2/bb/2p' sed2.txt
2 bb 2
2bb 2 222
[root@liupeng lp]#
將文件中找到以id開頭的行中的:3:替換成:5:(先用^id找出行):
[root@liupeng lp]# sed '/^id/s/5/77/' /etc/inittab
# inittab is only used by upstart for the default runlevel.
#
.....
#
id:77:initdefault:
[root@liupeng lp]#
將sed2.txt文件中的空格全部替換爲冒號:
[root@liupeng lp]# sed 's/ /:/g' sed2.txt
1:1:1
2:2:2
3:3:3
22:2:222
4:4:4
5:5:5
6:6:6
7:7:7
[root@liupeng lp]#
將sed2.txt文件中的空格全部替換成分號,同時將數字6全部替換成逗號:
[root@liupeng lp]# sed 's/ /;/g ; s/6/,/g' sed2.txt
1;1;1
2;2;2
3;3;3
22;2;222
4;4;4
5;5;5
,;,;,
7;7;7
[root@liupeng lp]#
在文件sed2.txt的2到3行前面加上註釋:
[root@liupeng lp]# sed -n '2,3s/^/#/p' sed2.txt
#2 2 2
#3 3 3
[root@liupeng lp]# cat sed2.txt
1 1 1
2 2 2
3 3 3
22 2 222
4 4 4
5 5 5
6 6 6
7 7 7
[root@liupeng lp]#
在文件sed2.txt的每行末尾加上問號:
[root@liupeng lp]# sed -n 's/$/?/p' sed2.txt
1 1 1?
2 2 2?
3 3 3?
22 2 222?
4 4 4?
5 5 5?
6 6 6?
7 7 7?
[root@liupeng lp]#
或:
[root@liupeng lp]# sed 's/$/?/' sed2.txt
1 1 1?
2 2 2?
3 3 3?
22 2 222?
4 4 4?
5 5 5?
6 6 6?
7 7 7?
[root@liupeng lp]#
1.5 sed的s編輯命令可以使用任意分隔符作爲定界符
例如:
把/etc/passwd文件中root開頭的行的/bin/bash替換成hahaha(用|做定界符):
[root@liupeng lp]# sed -n '/^root/s|/bin/bash|hahaha|p' /etc/passwd
root:x:0:0:root:/root:hahaha
[root@liupeng lp]#
以分號做定界符:
[root@liupeng lp]# sed -n '/^root/s;/bin/bash;hahaha;p' /etc/passwd
root:x:0:0:root:/root:hahaha
[root@liupeng lp]#
1.6 sed 命令的-i 選項
-i選項是直接修改文件,小心使用 !!
用法格式:sed -i ‘/模式/s/源字符/替換成/g’ 文件名
示例:用sed命令的-i選項,將sed2.txt文件中以數字22開頭的行中的22全部替換成字符a:
[root@liupeng lp]# cat sed2.txt
1 1 1
2 2 2
3 3 3
22 2 222
4 4 4
5 5 5
6 6 6
7 7 7
[root@liupeng lp]# sed -i '/^22/s/22/a/g' sed2.txt
[root@liupeng lp]# cat sed2.txt
1 1 1
2 2 2
3 3 3
a 2 a2
4 4 4
5 5 5
6 6 6
7 7 7
[root@liupeng lp]#
1.7 sed的編輯命令補充之:G命令
G:把緩存空間裏的東西追加到模式空間的行後。
例:在sed2.txt文件的每行後面加空行。
[root@liupeng lp]# sed 'G' sed2.txt
1 1 1
2 2 2
3 3 3
a 2 a2
4 4 4
5 5 5
6 6 6
7 7 7
[root@liupeng lp]# cat sed2.txt
1 1 1
2 2 2
3 3 3
a 2 a2
4 4 4
5 5 5
6 6 6
7 7 7
[root@liupeng lp]#
一個例子來理解2個模式:
在sed的工作原理中我們提到,sed工作在內存,有兩個空間:
- pattern space(模式空間):緩存空間,較多使用(模式空間裏處理一行內容後,會將這一行內容刪除。加載第2行內容);
- hold space(保留空間):臨時倉庫,很少使用。
下面我們舉個例子來理解一下這兩個空間。
首先新建一個test.txt文件,內容如下:
[root@liupeng lp]# cat test.txt
xiaomi
huawei
huawei
apple
huawei
samsung
huawei
[root@liupeng lp]#
接着我們執行命令“sed ‘/huawei/h;G’ test.txt”,會發現輸出的內容很值得思考:
[root@liupeng lp]# sed '/huawei/h;G' test.txt
xiaomi
huawei
huawei
huawei
huawei
apple
huawei
huawei
huawei
samsung
huawei
huawei
huawei
[root@liupeng lp]#
會如此顯示的原因如下:
①先查找huawei,如果符合條件就將這行的內容寫到hold space裏,接着執行G命令,就會將hold space裏的內容追加到pattern space後面,然後輸出到屏幕。
②因爲第一行是xiaomi,不符合/huawei/模式條件,所以不將xiaomi複製到hold space裏,又因爲hold space裏開始時默認是空的,所以會在xiaomi後面添加一行空行。
③第2行的內容剛好就是huawei,符合模塊的條件,就將huawei這行複製到hold space裏,替換了原來裏面的空的內容。接着執行G命令,又將huawei追加到pattern space空間的後面,所以有2個huawei,後面的行以此類推。
1.8 sed命令特殊用法
- &符號:&符號表示前面找到的模式匹配內容。
示例:找出/etc/passwd文件中uid100~999的,在後面都加個0
[root@liupeng lp]# cat -n /etc/passwd|sed -n -r 's/[0-9]{3}/&0/p'
12 games:x:12:1000:games:/usr/games:/sbin/nologin
17 usbmuxd:x:1130:113:usbmuxd user:/:/sbin/nologin
18 avahi-autoipd:x:1700:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
21 rtkit:x:4990:497:RealtimeKit:/proc:/sbin/nologin
22 abrt:x:1730:173::/etc/abrt:/sbin/nologin
26 saslauth:x:4980:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
30 nfsnobody:x:655034:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
31 pulse:x:4970:496:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
35 mysql:x:4960:493::/home/mysql:/bin/bash
[root@liupeng lp]#
- 標籤
標籤:sed使用圓括號定義替換模式中的部分字符。
標籤可以方便在後面引用,每行指令最多使用9個標籤。
示例1:用sed取出passwd裏面的第一列。
\1表示第一個標籤,用第一個標籤(^[0-Z]+)把前面符合第一個和第二個的全部取代:
[root@liupeng lp]# cat /etc/passwd|sed -r 's/(^[0-Z]+)(.*)/\1/'
root
bin
daemon
......
[root@liupeng lp]#
示例2:刪除/etc/passwd第一個字段.
思路:用第2個標籤(.*)把前面的符合第一個和第二個的全部取代。
[root@liupeng lp]# cat /etc/passwd | sed -r 's/(^[0-Z]+)(.*)/\2/'
:x:0:0:root:/root:/bin/bash
:x:1:1:bin:/bin:/sbin/nologin
:x:2:2:daemon:/sbin:/sbin/nologin
......
[root@liupeng lp]#
示例3:注意小括號之間有空格:
[root@liupeng lp]# echo aaa bbb ccc|sed -r 's/([a-z]+) ([a-z]+) ([a-z]+)/\3#\2#\1/'
ccc#bbb#aaa
[root@liupeng lp]#
1.9 sed的s命令中支持\t \n \s(正則裏表示空白)
具體示例在上面的代碼中有,用到\n換行時,前面不用加反斜槓來釋義。
2 練習
1.sed取出/etc/passwd文件的第一列。
2.sed將PATH環境變量中的冒號換成換行。
3.sed將PATH環境變量斜槓/換成斜槓\。
4.sed修改SELINUX配置文件從開啓變成禁用(/etc/sysconfig/selinux)。
5.去掉/etc/passwd文件中第二個地段的x。
6.修改/etc/inittab文件裏的3或者5修改爲6。
7.用sed命令刪除"cat -n /etc/passwd"每行前面的空格和數字。
(答案放在本文最後)。
答案:
1.sed取出/etc/passwd文件的第一列。
[root@liupeng lp]# cat /etc/passwd|sed -r 's/(^[0-Z]+)(.*)/\1/'
root
bin
daemon
......
[root@liupeng lp]#
–》\1表示第一個標籤
2.sed將PATH環境變量中的冒號換成換行。
[root@liupeng lp]# echo $PATH|sed 's/:/\n/g'
/usr/lib64/qt-3.3/bin
/usr/local/sbin
/usr/local/bin
/sbin
/bin
/usr/sbin
/usr/bin
/root/bin
/usr/local/python3.6.4/bin
[root@liupeng lp]# echo $PATH
/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/python3.6.4/bin
[root@liupeng lp]#
3.sed將PATH環境變量斜槓/換成斜槓\。
[root@liupeng lp]# echo $PATH|sed -r 's/\//\\/g'
\usr\lib64\qt-3.3\bin:\usr\local\sbin:\usr\local\bin:\sbin:\bin:\usr\sbin:\usr\bin:\root\bin:\usr\local\python3.6.4\bin
[root@liupeng lp]#
或者用井號來做定界符:
[root@liupeng lp]# echo $PATH|sed -r 's#/#\\#g'
\usr\lib64\qt-3.3\bin:\usr\local\sbin:\usr\local\bin:\sbin:\bin:\usr\sbin:\usr\bin:\root\bin:\usr\local\python3.6.4\bin
[root@liupeng lp]#
4.sed修改SELINUX配置文件從開啓變成禁用(/etc/sysconfig/selinux)。
[root@liupeng lp]# cat /etc/sysconfig/selinux|sed '/^SELINUX=/s/enforcing/disabled/g'
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
SELINUX=disabled
# SELINUXTYPE= can take one of these two values:
# targeted - Targeted processes are protected,
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
[root@liupeng lp]#
5.去掉/etc/passwd文件中第二個地段的x。
[root@liupeng lp]# cat /etc/passwd | sed 's/:x:/::/g'
root::0:0:root:/root:/bin/bash
bin::1:1:bin:/bin:/sbin/nologin
......
[root@liupeng lp]#
[root@liupeng lp]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
......
6.把/etc/inittab文件裏的3或者5修改爲6。
[root@liupeng lp]# cat /etc/inittab | sed -r '/^id/s/:[35]:/:6:/g'
......
id:6:initdefault:
[root@liupeng lp]# cat /etc/inittab
......
id:5:initdefault:
[root@liupeng lp]#
7.用sed命令刪除"cat -n /etc/passwd"每行前面的空格和數字。
方法1,用標籤來替換。
[root@liupeng lp]# cat -n /etc/passwd | sed -r 's/(\s+[0-9]+\s+)(.*)/\2/'
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@liupeng lp]#
方法2,使用正則去匹配,然後用空的內容去替換。
[root@liupeng lp]# cat -n /etc/passwd | sed -r 's/\s+[0-9]+\s+//'
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@liupeng lp]#
歡迎大家關注:
-----------END-------------