歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> SHELL編程 >> Linux.Shell編程筆記-流編輯Sed

Linux.Shell編程筆記-流編輯Sed

日期:2017/3/1 13:36:38   编辑:SHELL編程

第七章 流編輯

什麼是sed

挑選編輯器

UNIX/Linux世界葉,有許多的文本編輯器可供選擇。例如,最常使用的VI和emacs。在有了自己最熟悉的編輯利器後,才能輕松處理UNIX下各種管理和編輯任務。

像VI,emacs這類編輯器,被稱為交互式編輯器。交互式編輯器雖然很棒,但是當我們需要在程序中完成文本處理工作時,它就幫不上忙了。此時就需要一些能夠在命令行完成的編輯工具。

我們期待一切管理流程都能自動化,包括能夠以批處理的方式編輯文件。許多文本編輯的需求都是對文本的每一行進行相同的操作。這樣的處理就能夠用sed來完成。

sed號稱流編輯器。什麼是流編輯器呢?流編輯器可以對從管道這樣的標准輸入接收的數據進行編輯。因此,無需將要編輯的數據存儲在磁盤上的文件中。因為可以輕易將數據管道輸出到sed,所以,將sed用作強大的shell腳本中長而復雜的管道很容易。

Sed的版本

查看版本方式

[houchangren@ebsdi-23260-oozie ~]$ sed--version
GNU sed version 4.1.5
Copyright (C) 2003 Free SoftwareFoundation, Inc.
This is free software; see the source forcopying conditions.  There is NO
warranty; not even for MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE,
to the extent permitted by law.

Sed實例

Sed的工作方式

sed通過對輸入數據執行任意數量用戶指定的編輯操作(命令)。sed是基於行的,因此

按順序對每一行執行命令。然後,sed將其結果寫入標准輸出(stdout ),它不修改任何輸入

文件。

參數列表參考:

http://www.cnblogs.com/edwardlost/archive/2010/09/17/1829145.html

示例:

[houchangren@ebsdi-23260-oozie shell]$ head-n5 /etc/passwd > /tmp/passwd.bak
[houchangren@ebsdi-23260-oozie shell]$cat  /tmp/passwd.bak
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
[houchangren@ebsdi-23260-oozie shell]$ sed-e 'd'  /tmp/passwd.bak
[houchangren@ebsdi-23260-oozie shell]$ sed-e '1d' /tmp/passwd.bak
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
[houchangren@ebsdi-23260-oozie shell]$ sed-e '3d' /tmp/passwd.bak
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin

上方的‘d’就是參數應用就是默認的就是刪除每行,指定數字就刪除第幾行的記錄,第一次刪除了第一行1行顯示後四條。第二次刪除第3條,顯示剩余其他4條。

NOTE

在該例中,還有幾件事要注意:

1)根本沒有修改/tmp/passwd.bak這還是因為sed只讀取在命令行指定的文件,將其用作輸入-它不試圖修改該文件。

2)要注意的事是sed是面向行的。’d’命令不是簡單地告訴sed一下子刪除所有輸入數據。相反,sed逐行將/etc/passwd.bak的每一行讀入其稱為模式緩沖區的內部緩沖區一旦將一行讀入模式緩沖區,它就執行’d’命令,然後打印模式緩沖區的內容(在本例中沒有內容).如果不使用地址,命令將應用到所有行。

3)括起‘d’命令的單引號的用法。養成使用單引號來括起scd命令的習慣是個好主意,這樣可以禁用shell擴展。

Sed工作的地址范圍

指定命令的操作行區域,比如下邊1-2行和3-6行,當然沒有第6行,就只有多少刪除多少了。

[houchangren@ebsdi-23260-oozie shell]$ sed-e '1,2d' /tmp/passwd.bak
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
[houchangren@ebsdi-23260-oozie shell]$ sed-e '3,6d' /tmp/passwd.bak
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

sed忽略注釋

[houchangren@ebsdi-23260-oozie shell]$ cat/etc/rc.local
#!/bin/sh
#
# This script will be executed *after* allthe other init scripts.
# You can put your own initialization stuffin here if you don't
# want to do the full Sys V style initstuff.
 
touch /var/lock/subsys/local
hive --service hiveserver &
[houchangren@ebsdi-23260-oozie shell]$ sed-e '/^#/d' /etc/rc.local | more
 
touch /var/lock/subsys/local
hive --service hiveserver &
 
[houchangren@ebsdi-23260-oozie shell]$ sed-e '/^[^#]/d' /etc/rc.local | more
#!/bin/sh
#
# This script will be executed *after* allthe other init scripts.
# You can put your own initialization stuffin here if you don't
# want to do the full Sys V style initstuff.
規則表達式

Sed中使用的規則表達式字符

字符

描述

^

與行首匹配

$

與行尾匹配

.

與任意一個字符匹配

*

與前一個字符的零個或多個出現匹配

[]

與[]之內的所有字符匹配

Sed規則表達式實例

規則表達式

描述

/./

將與包含至少一個字符的任何行匹配

/../

將與包含至少兩個字符的任何行匹配

/^#/

將與以‘#’開頭的任意行匹配,通常這是注釋

/}$/

將與‘}’結束的任意行匹配

/} *$/

注意在}後面有一個空格,這將與‘}’後而跟隨零個或多個空格結束的任意行匹配配

/[abc]/

將與包含小寫字母‘a,b,c的任意行匹配

/^[abc]/

將與以a,b,c任何開始的任何行匹配

-n參數 這個選項告訴sed 除非明確要求打印模式空間,否則不這樣做。

[houchangren@ebsdi-23260-oozie shell]$ sed-n -e '/^[echo]/p' user_login.sh
echo " user $1 is on"
else
echo " user $1 is off"
 
[houchangren@ebsdi-23260-oozie shell]$ sed-n -e '/[abc]/p' user_login.sh
#!/bin/bash
function user_login(){
echo " user $1 is on"
echo " user $1 is off"
 
[houchangren@ebsdi-23260-oozie shell]$ cata.c
#include <stdio.h>
#include <math.H>
 
int main (){
// int base,n;
// scanf("%d,%d\n",&b,&n)
 
}
[houchangren@ebsdi-23260-oozie shell]$ sed-n -e '/main[[:space:]]*(/,/^ }/p' a.c | more
int main (){
// int base,n;
// scanf("%d,%d\n",&b,&n)
 
}
[houchangren@ebsdi-23260-oozie shell]$ sed-n -e '/^\//p' a.c | more
// int base,n;
// scanf("%d,%d\n",&b,&n)
 

強大的Sed功能

替換

替換公式: sed -e s[符號][要替換的字符][符號][替換後的字符][符號][g]

實例:

[houchangren@ebsdi-23260-oozie data]$ cattwister.txt    //查看一信息
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish. 
[houchangren@ebsdi-23260-oozie data]$ sed-e 's/wish/want/' twister.txt   //替換每一行的第一個匹配
I want to wish the wish you wish to wish,but if you wish the wish the witch
 wantes, I won't wish the wish you wish towish.
I want to wish the wish you wish to wish,but if you wish the wish the witch
 wantes, I won't wish the wish you wish towish.
I want to wish the wish you wish to wish,but if you wish the wish the witch
 wantes, I won't wish the wish you wish towish.
I want to wish the wish you wish to wish,but if you wish the wish the witch
 wantes, I won't wish the wish you wish towish. 
[houchangren@ebsdi-23260-oozie data]$ sed-e 's/wish/want/g' twister.txt  //替換匹配到的所有的
I want to want the want you want to want,but if you want the want the witch
 wantes, I won't want the want you want towant.
I want to want the want you want to want,but if you want the want the witch
 wantes, I won't want the want you want towant.
I want to want the want you want to want,but if you want the want the witch
 wantes, I won't want the want you want towant.
I want to want the want you want to want,but if you want the want the witch
 wantes, I won't want the want you want towant. 
[houchangren@ebsdi-23260-oozie data]$ sed-e '1,2s/wish/want/' twister.txt  //替換1到2行的第一個匹配
I want to wish the wish you wish to wish,but if you wish the wish the witch
 wantes, I won't wish the wish you wish towish.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish. 
[houchangren@ebsdi-23260-oozie data]$ sed-e '1,2s/wish/want/g' twister.txt  //替換1到2行的所有匹配
I want to want the want you want to want,but if you want the want the witch
 wantes, I won't want the want you want towant.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish.
I wish to wish the wish you wish to wish,but if you wish the wish the witch
 wishes, I won't wish the wish you wish towish. 
[houchangren@ebsdi-23260-oozie data]$

因為有的時候需要操作’/’符號,那麼再用‘/’線

來做符號就不方便了,可以改成其他的,比如冒號‘:’

[houchangren@ebsdi-23260-oozie data]$ cathivepath.txt
/usr/local/hive-0.7.1-cdh3u6/bin/hive
/usr/local/hive-0.7.1-cdh3u6/bin/hive
/usr/local/hive-0.7.1-cdh3u6/bin/hive
/usr/local/hive-0.7.1-cdh3u6/bin/hive
[houchangren@ebsdi-23260-oozie data]$ sed-e s:/usr/local:/usr/lib:g hivepath.txt
/usr/lib/hive-0.7.1-cdh3u6/bin/hive
/usr/lib/hive-0.7.1-cdh3u6/bin/hive
/usr/lib/hive-0.7.1-cdh3u6/bin/hive
/usr/lib/hive-0.7.1-cdh3u6/bin/hive

過濾所有的html標簽實例

[houchangren@ebsdi-23260-oozie data]$ cattest.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTDHTML 4.0 Transitional//EN">
<HTML>
 <HEAD>
 <TITLE> New Document </TITLE>
 <META NAME="Generator" CONTENT="EditPlus">
 <META NAME="Author" CONTENT="">
 <META NAME="Keywords" CONTENT="">
 <META NAME="Description" CONTENT="">
 </HEAD>
 
 <BODY>
 
 I'mtest html
 </BODY>
</HTML>
 
[houchangren@ebsdi-23260-oozie data]$ sed-e 's/<[^>]*>//g' test.html
 
New Document

I'mtest html

組合命令

組合多條命令

在同時使用多個命令的時候可以使用分號“;”

[houchangren@ebsdi-23260-oozie data]$ sed-e '=' fruit.txt  // 等號=是顯示行號
1
%%banae 
2
banana  
3
apple
4
Presimmon
5
%%banae 
6
apple 
7
Banana  
8
orange  
9
presimmon
[houchangren@ebsdi-23260-oozie data]$ sed-e '=;p' fruit.txt //顯示行號和打印默認會打印所以兩次
1
%%banae 
%%banae 
2
banana  
banana  
3
apple
apple
4
Presimmon
Presimmon
5
%%banae 
%%banae 
6
apple 
apple 
7
Banana  
Banana  
8
orange  
orange  
9
presimmon
presimmon
[houchangren@ebsdi-23260-oozie data]$ sed-n -e '=;p' fruit.txt //指定-n後打印p參數的命令
1
%%banae 
2
banana  
3
apple
4
Presimmon
5
%%banae 
6
apple 
7
Banana  
8
orange  
9
Persimmon
[houchangren@ebsdi-23260-oozie data]$ sed-n -e 'p' -e = fruit.txt  //-e可以指定多個命令
%%banae 
1
banana  
2
apple
3
Presimmon
4
%%banae 
5
apple 
6
Banana  
7
orange  
8
presimmon
9
 

有時候當太多的命令需要連接一起執行的時候-e可能也不夠使用了,可以使用-f指定文本,然後在文本中編寫命令

[houchangren@ebsdi-23260-oozie data]$ cathivepath.txt
/usr/local/hive-0.7.1-cdh3u6/bin/hive
/usr/local/hive-0.7.1-cdh3u6/bin/hive
/usr/local/hive-0.7.1-cdh3u6/bin/hive
/usr/local/hive-0.7.1-cdh3u6/bin/hive
//1d是刪除一行,接著是/usr/local替換成/usr/bin,接著打印,接著顯示行號
[houchangren@ebsdi-23260-oozie data]$ cat../sed/test.sed   
1d
s:/usr/local/:/usr/lib/:g
p
=
[houchangren@ebsdi-23260-oozie data]$ sed-n -f ../sed/test.sed  hivepath.txt
/usr/lib/hive-0.7.1-cdh3u6/bin/hive
2
/usr/lib/hive-0.7.1-cdh3u6/bin/hive
3
/usr/lib/hive-0.7.1-cdh3u6/bin/hive
4
將多條命令應用到一個地址范圍

在指定了一個地址范圍比如 1-5行,然後執行多個操作

[houchangren@ebsdi-23260-oozie data]$ head-n10 /etc/passwd > pwd.piece
[houchangren@ebsdi-23260-oozie data]$ catpwd.piece
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
news:x:9:13:news:/etc/news:

[houchangren@ebsdi-23260-oozie data]$ sed -n -e'1,5{s:/bin/bash:/bin/sh:g;s/:/|/g;p}' pwd.piece
[houchangren@ebsdi-23260-oozie data]$ sed-n -e '1,5{s:/bin/bash:/bin/sh:g;s/:/|/g;p}' pwd.piece
root|x|0|0|root|/root|/bin/sh
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
[houchangren@ebsdi-23260-oozie data]$
 
[houchangren@ebsdi-23260-oozie data]$ cat../sed/pwd.sed
1,5{
s:/bin/bash:/bin/sh:g
s/:/|/g
p
}
[houchangren@ebsdi-23260-oozie data]$ sed-n -f ../sed/pwd.sed pwd.piece
root|x|0|0|root|/root|/bin/sh
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
實例的例子

LINUX和DOS/Windows系統純文本格式的換行方式是不同的。這個腳本將UNIX風格的文本轉換成DOS/windows格式。你可能知道,基於DOS、windows的文本文件在每一行末尾有一個CR(回車)和LF(換行),而UNIX文本只有一個換行。有時可能需要將某unix文本移至

Windows系統,該腳本將為你執行必需的格式轉換.

>>> sed  -e  ‘s/$/\r/’myunix.txt > mydos.txt

在該腳本中,‘$’規則表達式將與行的末尾匹配,而`\r'告訴sed在其之前插入個回車。

在換行之前插入回車,每一行立即就以CR/LF結束。

反之,有好多的時候下載的網絡文件是dos/windows文件,在unix操作確實有問題,比如bash。用sed調用將把dos/windows格式的文本轉換成可信賴的unix格式

>>> sed –e ‘s/.$//’ mydos.txt >myunix.txt

該腳本的工作原理很簡單:替代規則表達式與一行的的最末字符匹配,而該字符恰好就是回車。我們用空字符替換它,從而將其從輸出中徹底刪除。如果使用改腳本,並注意到己經刪除了輸出中每行的最末字符,那麼,你就指定了已經是UNIX式的文本文件。

Sed實踐

要求:

1. 把“小明“的名字改成“李小明”;

2. 刪除頭三行

3. 顯示5-10行

4. 刪除包含“排除“的行

5. 顯示所有生日在Nov和Dec之間的行

6. 所有姓張開頭的行,前邊標記 ***

7. 用“試用期人員“替換包含”試用“的行

8. 把劉發明的生日 1986/11/11

9. 刪除所有的空白行

10. 寫一個腳本,將第一行插入Personnel File ,刪除所有以500結尾的工資,顯示文件內容,把電話號碼和生日顛倒一下,在文件的結尾添加the end。

11.把包含“試用”的行中姓名提取出來,然後正行替換成“試用人員:”+name

數據內容:

[houchangren@ebsdi-23260-oozie data]$ cat persons.txt
小明:010-68239343:我是經理:1988/01/10:5000
黎明:010-68239343:我是經理:1988/08/10:5000
張學友:010-68239343:我是經理:1988/04/10:5000
 
周雲飛:010-68239343:業務排除了。:1988/10/10:500
麗澤卡:010-68239343:沒有描述:1988/12/10:2000
劉發明:010-68239343:沒有描述:1988/11/10:5340
 
大荒西:010-68239343:沒有描述:1988/10/10:1000
斯蒂芬:010-68239343:沒有描述:1988/10/10:1000
甄格大:010-68239343:試用期中.:1988/10/10:200
 
任務操作:
1.
[houchangren@ebsdi-23260-oozie data]$ sed-n -e 's:小明:李小明:gp' persons.txt
李小明:010-68239343:我是經理:1988/01/10:5000
2.
[houchangren@ebsdi-23260-oozie data]$ sed -e '1,3d' persons.txt
 
周雲飛:010-68239343:業務排除了。:1988/10/10:500
麗澤卡:010-68239343:沒有描述:1988/12/10:2000
劉發明:010-68239343:沒有描述:1988/11/10:5340
 
大荒西:010-68239343:沒有描述:1988/10/10:1000
斯蒂芬:010-68239343:沒有描述:1988/10/10:1000
甄格大:010-68239343:試用期中.:1988/10/10:200
3.
周雲飛:010-68239343:業務排除了。:1988/10/10:500
麗澤卡:010-68239343:沒有描述:1988/12/10:2000
劉發明:010-68239343:沒有描述:1988/11/10:5340
 
4.
[houchangren@ebsdi-23260-oozie data]$ sed -e '/排除/d' persons.txt
小明:010-68239343:我是經理:1988/01/10:5000
黎明:010-68239343:我是經理:1988/08/10:5000
張學友:010-68239343:我是經理:1988/04/10:5000
 
麗澤卡:010-68239343:沒有描述:1988/12/10:2000
劉發明:010-68239343:沒有描述:1988/11/10:5340
 
大荒西:010-68239343:沒有描述:1988/10/10:1000
斯蒂芬:010-68239343:沒有描述:1988/10/10:1000
甄格大:010-68239343:試用期中.:1988/10/10:200
 
5.
[houchangren@ebsdi-23260-oozie data]$ sed -n '/[:::][0-9]*[:/:]1[1-2]/p' persons.txt
麗澤卡:010-68239343:沒有描述:1988/12/10:2000
劉發明:010-68239343:沒有描述:1988/11/10:5340
6.
[houchangren@ebsdi-23260-oozie data]$ sed -n 's/^張/***張/p' persons.txt
***張學友:010-68239343:我是經理:1988/04/10:5000
 
7.
[houchangren@ebsdi-23260-oozie data]$ sed -e 's/^.*試用.*$/試用期人員/g' persons.txt
小明:010-68239343:我是經理:1988/01/10:5000
黎明:010-68239343:我是經理:1988/08/10:5000
張學友:010-68239343:我是經理:1988/04/10:5000
 
周雲飛:010-68239343:業務排除了。:1988/10/10:500
麗澤卡:010-68239343:沒有描述:1988/12/10:2000
劉發明:010-68239343:沒有描述:1988/11/10:5340
 
大荒西:010-68239343:沒有描述:1988/10/10:1000
斯蒂芬:010-68239343:沒有描述:1988/10/10:1000
試用期人員
 
8.
[houchangren@ebsdi-23260-oozie data]$ sed -n -e '/劉發明/s/:[0-9]*\/.*\/.*:/:1986\/11\/11:/gp' persons.txt
劉發明:010-68239343:沒有描述:1986/11/11:5340
9.
[houchangren@ebsdi-23260-oozie data]$ sed -e '/^$/d' persons.txt
小明:010-68239343:我是經理:1988/01/10:5000
黎明:010-68239343:我是經理:1988/08/10:5000
張學友:010-68239343:我是經理:1988/04/10:5000
周雲飛:010-68239343:業務排除了。:1988/10/10:500
麗澤卡:010-68239343:沒有描述:1988/12/10:2000
劉發明:010-68239343:沒有描述:1988/11/10:5340
大荒西:010-68239343:沒有描述:1988/10/10:1000
斯蒂芬:010-68239343:沒有描述:1988/10/10:1000
甄格大:010-68239343:試用期中.:1988/10/10:200
 
10.
 
[houchangren@ebsdi-23260-oozie data]$ cat ../sed/person.sed
/500$/d
s/\(.*\)\(:.*:\)\(.*\)\(:.*:\)\(.*\)/\1\4\3\2\5/g
1i personnel file
$a the end
 
[houchangren@ebsdi-23260-oozie data]$sed  -f ../sed/person.sed persons.txt
personnel file
小明:1988/01/10:我是經理:010-68239343:5000
黎明:1988/08/10:我是經理:010-68239343:5000
張學友:1988/04/10:我是經理:010-68239343:5000
 
麗澤卡:1988/12/10:沒有描述:010-68239343:2000
劉發明:1988/11/10:沒有描述:010-68239343:5340
 
大荒西:1988/10/10:沒有描述:010-68239343:1000
斯蒂芬:1988/10/10:沒有描述:010-68239343:1000
甄格大:1988/10/10:試用期中.:010-68239343:200
 
the end
 
11.
[houchangren@ebsdi-23260-oozie data]$ sed -n -e '/試用/s/\(.*\):.*:.*:.*:.*/試用期人員:\1/gp' persons.txt | more
試用期人員:甄格大
Copyright © Linux教程網 All Rights Reserved