awk和sed (十二)

【教程主題】:4.awksedhtml

【主要內容】
mysql

1awk 程序員

     AWK是貝爾實驗室1977年搞出來的文本出現神器.之因此叫AWK是由於其取了三位創始人 Alfred AhoPeter Weinberger, 和 Brian Kernighan 的Family Name的首字符。要學AWK,就得提一提AWK的一本至關經典的書《The AWK Programming Language》,它在豆瓣上的評分是9.4分!在亞馬遜上竟然賣1022.30元 正則表達式

Awk和sed 第二版 sql

我從netstat命令中提取了以下信息做爲用例: shell

$ cat netstat.txt 編程

Proto Recv-Q Send-Q Local-Address          Foreign-Address             State 數組

tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN app

tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN tcp

tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN

tcp        0      0 coolshell.cn:80        124.205.5.146:18245         TIME_WAIT

tcp        0      0 coolshell.cn:80        61.140.101.185:37538        FIN_WAIT2

tcp        0      0 coolshell.cn:80        110.194.134.189:1032        ESTABLISHED

tcp        0      0 coolshell.cn:80        123.169.124.111:49809       ESTABLISHED

tcp        0      0 coolshell.cn:80        116.234.127.77:11502        FIN_WAIT2

tcp        0      0 coolshell.cn:80        123.169.124.111:49829       ESTABLISHED

tcp        0      0 coolshell.cn:80        183.60.215.36:36970         TIME_WAIT

tcp        0   4166 coolshell.cn:80        61.148.242.38:30901         ESTABLISHED

tcp        0      1 coolshell.cn:80        124.152.181.209:26825       FIN_WAIT1

tcp        0      0 coolshell.cn:80        110.194.134.189:4796        ESTABLISHED

tcp        0      0 coolshell.cn:80        183.60.212.163:51082        TIME_WAIT

tcp        0      1 coolshell.cn:80        208.115.113.92:50601        LAST_ACK

tcp        0      0 coolshell.cn:80        123.169.124.111:49840       ESTABLISHED

tcp        0      0 coolshell.cn:80        117.136.20.85:50025         FIN_WAIT2

tcp        0      0 :::22                  :::*                        LISTEN

下面是最簡單最經常使用的awk示例,其輸出第1列和第4例,

· 其中單引號中的被大括號括着的就是awk的語句,注意,其只能被單引號包含。

· 其中的$1..$n表示第幾例。注:$0表示整個行。

$ awk '{print $1, $4}' netstat.txt

Proto Local-Address

tcp 0.0.0.0:3306

tcp 0.0.0.0:80

tcp 127.0.0.1:9000

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp coolshell.cn:80

tcp :::22

咱們再來看看awk的格式化輸出,和C語言的printf沒什麼兩樣:

$ awk'{printf "%-8s %-8s %-8s %-18s %-22s %-15s\n",$1,$2,$3,$4,$5,$6}'netstat.txt

Proto    Recv-Q   Send-Q   Local-Address      Foreign-Address        State

tcp      0        0        0.0.0.0:3306       0.0.0.0:*              LISTEN

tcp      0        0        0.0.0.0:80         0.0.0.0:*              LISTEN

tcp      0        0        127.0.0.1:9000     0.0.0.0:*              LISTEN

tcp      0        0        coolshell.cn:80    124.205.5.146:18245    TIME_WAIT

tcp      0        0        coolshell.cn:80    61.140.101.185:37538   FIN_WAIT2

tcp      0        0        coolshell.cn:80    110.194.134.189:1032   ESTABLISHED

tcp      0        0        coolshell.cn:80    123.169.124.111:49809  ESTABLISHED

tcp      0        0        coolshell.cn:80    116.234.127.77:11502   FIN_WAIT2

tcp      0        0        coolshell.cn:80    123.169.124.111:49829  ESTABLISHED

tcp      0        0        coolshell.cn:80    183.60.215.36:36970    TIME_WAIT

tcp      0        4166     coolshell.cn:80    61.148.242.38:30901    ESTABLISHED

tcp      0        1        coolshell.cn:80    124.152.181.209:26825  FIN_WAIT1

tcp      0        0        coolshell.cn:80    110.194.134.189:4796   ESTABLISHED

tcp      0        0        coolshell.cn:80    183.60.212.163:51082   TIME_WAIT

tcp      0        1        coolshell.cn:80    208.115.113.92:50601   LAST_ACK

tcp      0        0        coolshell.cn:80    123.169.124.111:49840  ESTABLISHED

tcp      0        0        coolshell.cn:80    117.136.20.85:50025    FIN_WAIT2

tcp      0        0        :::22              :::*                   LISTEN

 
 
 
 
過濾記錄

咱們再來看看如何過濾記錄(下面過濾條件爲:第三列的值爲0 && 第6列的值爲LISTEN)

$ awk '$3==0 && $6=="LISTEN" ' netstat.txt

tcp        0      0 0.0.0.0:3306               0.0.0.0:*              LISTEN

tcp        0      0 0.0.0.0:80                 0.0.0.0:*              LISTEN

tcp        0      0 127.0.0.1:9000             0.0.0.0:*              LISTEN

tcp        0      0 :::22                      :::*                   LISTEN

其中的「==」爲比較運算符。其餘比較運算符:!=, <, < >=, < p>

咱們來看看各類過濾記錄的方式:

$ awk' $3>0 {print $0}'netstat.txt

Proto Recv-Q Send-Q Local-Address          Foreign-Address             State

tcp        0   4166 coolshell.cn:80        61.148.242.38:30901         ESTABLISHED

tcp        0      1 coolshell.cn:80        124.152.181.209:26825       FIN_WAIT1

tcp        0      1 coolshell.cn:80        208.115.113.92:50601        LAST_ACK

若是咱們須要表頭的話,咱們能夠引入內建變量NR:

$ awk '$3==0 && $6=="LISTEN" || NR==1 '  netstat.txt

Proto Recv-Q Send-Q Local-Address          Foreign-Address             State

tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN

tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN

tcp        0      0 :::22                  :::*                        LISTEN

再加上格式化輸出:

$ awk'$3==0 && $6=="LISTEN" || NR==1 {printf "%-20s %-20s %s\n",$4,$5,$6}'netstat.txt

Local-Address        Foreign-Address      State

0.0.0.0:3306         0.0.0.0:*            LISTEN

0.0.0.0:80           0.0.0.0:*            LISTEN

127.0.0.1:9000       0.0.0.0:*            LISTEN

:::22                :::*                 LISTEN

內建變量

說到了內建變量,咱們能夠來看看awk的一些內建變量:

$0

當前記錄(這個變量中存放着整個行的內容)

$1~$n

當前記錄的第n個字段,字段間由FS分隔

FS

輸入字段分隔符 默認是空格或Tab

NF

當前記錄中的字段個數,就是有多少列

NR

已經讀出的記錄數,就是行號,從1開始,若是有多個文件話,這個值也是不斷累加中。

FNR

當前記錄數,與NR不一樣的是,這個值會是各個文件本身的行號

RS

輸入的記錄分隔符, 默認爲換行符

OFS

輸出字段分隔符, 默認也是空格

ORS

輸出的記錄分隔符,默認爲換行符

FILENAME

當前輸入文件的名字

怎麼使用呢,好比:咱們若是要輸出行號:

$ awk'$3==0 && $6=="ESTABLISHED" || NR==1 {printf "%02s %s %-20s %-20s %s\n",NR, FNR, $4,$5,$6}'netstat.txt

01 1 Local-Address        Foreign-Address      State

07 7 coolshell.cn:80      110.194.134.189:1032 ESTABLISHED

08 8 coolshell.cn:80      123.169.124.111:49809 ESTABLISHED

10 10 coolshell.cn:80      123.169.124.111:49829 ESTABLISHED

14 14 coolshell.cn:80      110.194.134.189:4796 ESTABLISHED

17 17 coolshell.cn:80      123.169.124.111:49840 ESTABLISHED

指定分隔符

$  awk 'BEGIN{FS=":"} {print $1,$3,$6}' /etc/passwd

root 0 /root

bin 1 /bin

daemon 2 /sbin

adm 3 /var/adm

lp 4 /var/spool/lpd

sync5 /sbin

shutdown6 /sbin

halt 7 /sbin

上面的命令也等價於:(-F的意思就是指定分隔符)

$ awk-F: '{print $1,$3,$6}'/etc/passwd

注:若是你要指定多個分隔符,你能夠這樣來:

awk-F '[;:]'

 

再來看一個以\t做爲分隔符輸出的例子(下面使用了/etc/passwd文件,這個文件是以:分隔的):

$ awk-F: '{print $1,$3,$6}'OFS="\t"/etc/passwd

root    0       /root

bin     1       /bin

daemon  2       /sbin

adm     3       /var/adm

lp      4       /var/spool/lpd

sync5       /sbin

字符串匹配

咱們再來看幾個字符串匹配的示例:

$ awk '$6 ~ /FIN/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt

1       Local-Address   Foreign-Address State

6       coolshell.cn:80 61.140.101.185:37538    FIN_WAIT2

9       coolshell.cn:80 116.234.127.77:11502    FIN_WAIT2

13      coolshell.cn:80 124.152.181.209:26825   FIN_WAIT1

18      coolshell.cn:80 117.136.20.85:50025     FIN_WAIT2

$ $ awk '$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt

1       Local-Address   Foreign-Address State

5       coolshell.cn:80 124.205.5.146:18245     TIME_WAIT

6       coolshell.cn:80 61.140.101.185:37538    FIN_WAIT2

9       coolshell.cn:80 116.234.127.77:11502    FIN_WAIT2

11      coolshell.cn:80 183.60.215.36:36970     TIME_WAIT

13      coolshell.cn:80 124.152.181.209:26825   FIN_WAIT1

15      coolshell.cn:80 183.60.212.163:51082    TIME_WAIT

18      coolshell.cn:80 117.136.20.85:50025     FIN_WAIT2

上面的第一個示例匹配FIN狀態, 第二個示例匹配WAIT字樣的狀態。其實 ~ 表示模式開始。/ /中是模式。這就是一個正則表達式的匹配。

其實awk能夠像grep同樣的去匹配第一行,就像這樣:

$ awk '/LISTEN/' netstat.txt

tcp        0      0 0.0.0.0:3306            0.0.0.0:*               LISTEN

tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN

tcp        0      0 127.0.0.1:9000          0.0.0.0:*               LISTEN

tcp        0      0 :::22                   :::*                    LISTEN

咱們可使用 「/FIN|TIME/」 來匹配 FIN 或者 TIME :

$ awk'$6 ~ /FIN|TIME/ || NR==1 {print NR,$4,$5,$6}'OFS="\t"netstat.txt

1       Local-Address   Foreign-Address State

5       coolshell.cn:80 124.205.5.146:18245     TIME_WAIT

6       coolshell.cn:80 61.140.101.185:37538    FIN_WAIT2

9       coolshell.cn:80 116.234.127.77:11502    FIN_WAIT2

11      coolshell.cn:80 183.60.215.36:36970     TIME_WAIT

13      coolshell.cn:80 124.152.181.209:26825   FIN_WAIT1

15      coolshell.cn:80 183.60.212.163:51082    TIME_WAIT

18      coolshell.cn:80 117.136.20.85:50025     FIN_WAIT2

再來看看模式取反的例子:

$ awk'$6 !~ /WAIT/ || NR==1 {print NR,$4,$5,$6}'OFS="\t"netstat.txt

1       Local-Address   Foreign-Address State

2       0.0.0.0:3306    0.0.0.0:*       LISTEN

3       0.0.0.0:80      0.0.0.0:*       LISTEN

4       127.0.0.1:9000  0.0.0.0:*       LISTEN

7       coolshell.cn:80 110.194.134.189:1032    ESTABLISHED

8       coolshell.cn:80 123.169.124.111:49809   ESTABLISHED

10      coolshell.cn:80 123.169.124.111:49829   ESTABLISHED

12      coolshell.cn:80 61.148.242.38:30901     ESTABLISHED

14      coolshell.cn:80 110.194.134.189:4796    ESTABLISHED

16      coolshell.cn:80 208.115.113.92:50601    LAST_ACK

17      coolshell.cn:80 123.169.124.111:49840   ESTABLISHED

19      :::22   :::*    LISTEN

或是:

Awk '!/WAIT/' netstat.txt

 

折分文件

awk拆分文件很簡單,使用重定向就行了。下面這個例子,是按第6例分隔文件,至關的簡單(其中的NR!=1表示不處理表頭)。

$ awk 'NR!=1{print > $6}' netstat.txt

$ ls

ESTABLISHED  FIN_WAIT1  FIN_WAIT2  LAST_ACK  LISTEN  netstat.txt  TIME_WAIT

$ cat ESTABLISHED

tcp        0      0 coolshell.cn:80        110.194.134.189:1032        ESTABLISHED

tcp        0      0 coolshell.cn:80        123.169.124.111:49809       ESTABLISHED

tcp        0      0 coolshell.cn:80        123.169.124.111:49829       ESTABLISHED

tcp        0   4166 coolshell.cn:80        61.148.242.38:30901         ESTABLISHED

tcp        0      0 coolshell.cn:80        110.194.134.189:4796        ESTABLISHED

tcp        0      0 coolshell.cn:80        123.169.124.111:49840       ESTABLISHED

$ cat FIN_WAIT1

tcp        0      1 coolshell.cn:80        124.152.181.209:26825       FIN_WAIT1

$ cat FIN_WAIT2

tcp        0      0 coolshell.cn:80        61.140.101.185:37538        FIN_WAIT2

tcp        0      0 coolshell.cn:80        116.234.127.77:11502        FIN_WAIT2

tcp        0      0 coolshell.cn:80        117.136.20.85:50025         FIN_WAIT2

$ cat LAST_ACK

tcp        0      1 coolshell.cn:80        208.115.113.92:50601        LAST_ACK

$ cat LISTEN

tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN

tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN

tcp        0      0 :::22                  :::*                        LISTEN

$ cat TIME_WAIT

tcp        0      0 coolshell.cn:80        124.205.5.146:18245         TIME_WAIT

tcp        0      0 coolshell.cn:80        183.60.215.36:36970         TIME_WAIT

tcp        0      0 coolshell.cn:80        183.60.212.163:51082        TIME_WAIT

你也能夠把指定的列輸出到文件:

awk 'NR!=1{print $4,$5 < $6}'netstat.txt

再複雜一點:(注意其中的if-else-if語句,可見awk實際上是個腳本解釋器)

$ awk 'NR!=1{if($6 ~ /TIME|ESTABLISHED/) print > "1.txt";

else if($6 ~ /LISTEN/) print > "2.txt";

else print > "3.txt" }' netstat.txt

$ ls?.txt

1.txt  2.txt  3.txt

$ cat1.txt

tcp        0      0 coolshell.cn:80        124.205.5.146:18245         TIME_WAIT

tcp        0      0 coolshell.cn:80        110.194.134.189:1032        ESTABLISHED

tcp        0      0 coolshell.cn:80        123.169.124.111:49809       ESTABLISHED

tcp        0      0 coolshell.cn:80        123.169.124.111:49829       ESTABLISHED

tcp        0      0 coolshell.cn:80        183.60.215.36:36970         TIME_WAIT

tcp        0   4166 coolshell.cn:80        61.148.242.38:30901         ESTABLISHED

tcp        0      0 coolshell.cn:80        110.194.134.189:4796        ESTABLISHED

tcp        0      0 coolshell.cn:80        183.60.212.163:51082        TIME_WAIT

tcp        0      0 coolshell.cn:80        123.169.124.111:49840       ESTABLISHED

$ cat2.txt

tcp        0      0 0.0.0.0:3306           0.0.0.0:*                   LISTEN

tcp        0      0 0.0.0.0:80             0.0.0.0:*                   LISTEN

tcp        0      0 127.0.0.1:9000         0.0.0.0:*                   LISTEN

tcp        0      0 :::22                  :::*                        LISTEN

$ cat3.txt

tcp        0      0 coolshell.cn:80        61.140.101.185:37538        FIN_WAIT2

tcp        0      0 coolshell.cn:80        116.234.127.77:11502        FIN_WAIT2

tcp        0      1 coolshell.cn:80        124.152.181.209:26825       FIN_WAIT1

tcp        0      1 coolshell.cn:80        208.115.113.92:50601        LAST_ACK

tcp        0      0 coolshell.cn:80        117.136.20.85:50025         FIN_WAIT2

統計

下面的命令計算全部的C文件,CPP文件和H文件的文件大小總和。

$ ls-l  *.cpp *.c *.h | awk'{sum+=$5} END {print sum}'

2511401

咱們再來看一個統計各個connection狀態的用法:(咱們能夠看到一些編程的影子了,你們都是程序員我就不解釋了。注意其中的數組的用法)

$ awk 'NR!=1{a[$6]++;} END {for (i in a) print i ", " a[i];}' netstat.txt

TIME_WAIT, 3

FIN_WAIT1, 1

ESTABLISHED, 6

FIN_WAIT2, 3

LAST_ACK, 1

LISTEN, 4

再來看看統計每一個用戶的進程的佔了多少內存(注:sum的RSS那一列)

$ ps aux | awk 'NR!=1{a[$1]+=$6;} END { for(i in a) print i ", " a[i]"KB";}'

dbus, 540KB

mysql, 99928KB

www, 3264924KB

root, 63644KB

hchen, 6020KB

awk腳本

在上面咱們能夠看到一個END關鍵字。END的意思是「處理完全部的行的標識」,即然說到了END就有必要介紹一下BEGIN,這兩個關鍵字意味着執行前和執行後的意思,語法以下:

· BEGIN{ 這裏面放的是執行前的語句 }

· END {這裏面放的是處理完全部的行後要執行的語句 }

· {這裏面放的是處理每一行時要執行的語句}

爲了說清楚這個事,咱們來看看下面的示例:

假設有這麼一個文件(學生成績表):

$ catscore.txt

Marry   2143 78 84 77

Jack    2321 66 78 45

Tom     2122 48 77 71

Mike    2537 87 97 95

Bob     2415 40 57 62

咱們的awk腳本以下(我沒有寫有命令行上是由於命令行上不易讀,另外也在介紹另外一種用法):

$ cat cal.awk

#!/bin/awk -f

#運行前

BEGIN {

math = 0

english = 0

computer = 0

printf"NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"

printf"---------------------------------------------\n"

}

#運行中

{

math+=$3

english+=$4

computer+=$5

printf"%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5

}

#運行後

END {

printf"---------------------------------------------\n"

printf"  TOTAL:%10d %8d %8d \n", math, english, computer

printf"AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR

}

咱們來看一下執行結果:(也能夠這樣運行 ./cal.awk score.txt)

$ awk-f cal.awk score.txt

NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL

---------------------------------------------

Marry  2143     78       84       77      239

Jack   2321     66       78       45      189

Tom    2122     48       77       71      196

Mike   2537     87       97       95      279

Bob    2415     40       57       62      159

---------------------------------------------

TOTAL:       319      393      350

AVERAGE:     63.80    78.60    70.00

環境變量

即然說到了腳本,咱們來看看怎麼和環境變量交互:(使用-v參數和ENVIRON,使用ENVIRON的環境變量須要export)

$ x=5

$ y=10

$ export y

$ echo$x $y

5 10

awk -v val=$x '{print $1, $2, $3, $4+val, $5+ENVIRON["y"]}' OFS="\t" score.txt

Marry   2143    78      89      87

Jack    2321    66      83      55

Tom     2122    48      82      81

Mike    2537    87      102     105

Bob     2415    40      62      72

最後,咱們再來看幾個小例子:

#file文件中找出長度大於80的行

awk 'length>80' file

#按鏈接數查看客戶端IP

netstat -ntu | awk'{print $5}'| cut-d: -f1 | sort| uniq-c | sort-nr

#打印99乘法表

Seq 9 | sed'H;g'| awk-vRS='''{for(i=1;i< NFiprintfdxd dsquot i NR iNR i="=NR?"\n":"\t")}'

關於其中的一些知識點能夠參看gawk的手冊

· 內建變量,參看:http://www.gnu.org/software/gawk/manual/gawk.html#Built_002din-Variables

· 流控方面,參看:http://www.gnu.org/software/gawk/manual/gawk.html#Statements

· 內建函數,參看:http://www.gnu.org/software/gawk/manual/gawk.html#Built_002din

· 正則表達式,參看:http://www.gnu.org/software/gawk/manual/gawk.html#Regexp

 

 

2sed

 

sed全名叫stream editor,流編輯器,用程序的方式來編輯文本,至關的hacker啊。sed基本上就是玩正則模式匹配,因此,玩sed的人,正則表達式通常都比較強。

一樣,本篇文章不會說sed的所有東西,你能夠參看sed的手冊

用s命令替換

我使用下面的這段文本作演示:

$ cat pets.txt

This is my cat

my cat's name is betty

This is my dog

my dog's name is frank

This is my fish

my fish's name is george

This is my goat

my goat's name is adam

把其中的my字符串替換成Hao Chen’s,下面的語句應該很好理解(s表示替換命令,/my/表示匹配my,/Hao Chen’s/表示把匹配替換成Hao Chen’s,/g 表示一行上的替換全部的匹配):

$ sed "s/my/Hao Chen's/g" pets.txt

This is Hao Chen's cat

Hao Chen's cat's name is betty

This is Hao Chen's dog

Hao Chen's dog's name is frank

This is Hao Chen's fish

Hao Chen's fish's name is george

This is Hao Chen's goat

Hao Chen's goat's name is adam

注意:若是你要使用單引號,那麼你沒辦法經過\’這樣來轉義,就有雙引號就能夠了,在雙引號內能夠用\」來轉義。

再注意:上面的sed並無對文件的內容改變,只是把處理事後的內容輸出,若是你要寫回文件,你可使用重定向,如:

$ sed"s/my/Hao Chen's/g"pets.txt > hao_pets.txt

或使用 -i 參數直接修改文件內容:

$ sed -i "s/my/Hao Chen's/g" pets.txt

在每一行最前面加點東西:

$ sed 's/^/#/g' pets.txt

#This is my cat

#  my cat's name is betty

#This is my dog

#  my dog's name is frank

#This is my fish

#  my fish's name is george

#This is my goat

#  my goat's name is adam

在每一行最後面加點東西:

 

$ sed 's/$/ --- /g' pets.txt

This is my cat---

my cat's name is betty ---

This is my dog ---

my dog's name is frank ---

This is my fish ---

my fish's name is george ---

This is my goat ---

my goat's name is adam ---

順手介紹一下正則表達式的一些最基本的東西:

· ^ 表示一行的開頭。如:/^#/ 以#開頭的匹配。

· $ 表示一行的結尾。如:/}$/ 以}結尾的匹配。

· \< 表示詞首。 如 \<abc 表示以 abc 爲首的詞。

· \> 表示詞尾。 如 abc\> 表示以 abc 結尾的詞。

· . 表示任何單個字符。

· * 表示某個字符出現了0次或屢次。

· [ ] 字符集合。 如:[abc]表示匹配a或b或c,還有[a-zA-Z]表示匹配全部的26個字符。若是其中有^表示反,如[^a]表示非a的字符

正規則表達式是一些很牛的事,好比咱們要去掉某html中的tags:

html.txt

< code>b<This</>b< is what < code>spanstyle="text-decoration: underline;"<I</>span< meant. Understand?

看看咱們的sed命令

若是你這樣搞的話,就會有問題

$ sed 's/< >//g' html.txt

Understand?

要解決上面的那個問題,就得像下面這樣。

其中的'[^<]' 指定了除了<的字符重複0次或屢次。

sed 's/<[^>]*>//g' html.txt

This is what I meant. Understand?

咱們再來看看指定須要替換的內容:

$ sed"3s/my/your/g"pets.txt

This is my cat

my cat's name is betty

This is your dog

my dog's name is frank

This is my fish

my fish's name is george

This is my goat

my goat's name is adam

下面的命令只替換第3到第6行的文本。

$ sed "3,6s/my/your/g"pets.txt

This is my cat

my cat's name is betty

This is your dog

your dog's name is frank

This is your fish

your fish's name is george

This is my goat

my goat's name is adam

 

$ cat my.txt

This is my cat, my cat's name is betty

This is my dog, my dog's name is frank

This is my fish, my fish's name is george

This is my goat, my goat's name is adam

 

只替換每一行的第一個s:

$ sed 's/s/S/1' my.txt

ThiS is my cat, my cat's name is betty

ThiS is my dog, my dog's name is frank

ThiS is my fish, my fish's name is george

ThiS is my goat, my goat's name is adam

只替換每一行的第二個s:

$ sed's/s/S/2'my.txt

This iS my cat, my cat's name is betty

This iS my dog, my dog's name is frank

This iS my fish, my fish's name is george

This iS my goat, my goat's name is adam

只替換第一行的第3個之後的s:

$ sed's/s/S/3g'my.txt

This is my cat, my cat'S name iS betty

This is my dog, my dog'S name iS frank

This is my fiSh, my fiSh'S name iS george

This is my goat, my goat'S name iS adam

多個匹配

若是咱們須要一次替換多個模式,可參看下面的示例:(第一個模式把第一行到第三行的my替換成your,第二個則把第3行之後的This替換成了That)

$ sed '1,3s/my/your/g; 3,$s/This/That/g'my.txt

This is your cat, your cat's name is betty

This is your dog, your dog's name is frank

That is your fish, your fish's name is george

That is my goat, my goat's name is adam

上面的命令等價於:(注:下面使用的是sed的-e命令行參數)

Sed -e  '1,3s/my/your/g' -e  '3,$s/This/That/g' my.txt

咱們可使用&來當作被匹配的變量,而後能夠在基本左右加點東西。以下所示:

$ sed 's/my/[&]/g' my.txt

This is [my] cat, [my] cat's name is betty

This is [my] dog, [my] dog's name is frank

This is [my] fish, [my] fish's name is george

This is [my] goat, [my] goat's name is adam

圓括號匹配

使用圓括號匹配的示例:(圓括號括起來的正則表達式所匹配的字符串會能夠當成變量來使用,sed中使用的是\1,\2…)


sed 's/This is my \([^,]*\),.*is \(.*\)/\1:\2/g' my.txt

cat:betty

dog:frank

fish:george

goat:adam

上面這個例子中的正則表達式有點複雜,解開以下(去掉轉義字符):

正則爲:This is my ([^,]*),.*is (.*)
匹配爲:This is my (cat),……….is (betty)

而後:\1就是cat,\2就是betty

sed的命令

讓咱們回到最一開始的例子pets.txt,讓咱們來看幾個命令:

N命令

先來看N命令 —— 把下一行的內容歸入當成緩衝區作匹配。

下面的的示例會把原文本中的偶數行歸入奇數行匹配,而s只匹配並替換一次,因此,就成了下面的結果:

$ sed'N;s/my/your/'pets.txt

This is your cat

my cat's name is betty

This is your dog

my dog's name is frank

This is your fish

my fish's name is george

This is your goat

my goat's name is adam

也就是說,原來的文件成了:

This is my cat\n  my cat's name is betty

This is my dog\n  my dog's name is frank

This is my fish\n  my fish's name is george

This is my goat\n  my goat's name is adam

這樣一來,下面的例子你就明白了,

$ sed'N;s/\n/,/'pets.txt

This is my cat,  my cat's name is betty

This is my dog,  my dog's name is frank

This is my fish,  my fish's name is george

This is my goat,  my goat's name is adam

a命令和i命令

a命令就是append, i命令就是insert,它們是用來添加行的。如:

# 其中的1i代表,其要在第1行前插入一行(insert)

$ sed "1 i This is my monkey, my monkey's name is wukong"my.txt

This is my monkey, my monkey's name is wukong

This is my cat, my cat's name is betty

This is my dog, my dog's name is frank

This is my fish, my fish's name is george

This is my goat, my goat's name is adam

# 其中的1a代表,其要在最後一行後追加一行(append)

$ sed"$ a This is my monkey, my monkey's name is wukong"my.txt

This is my cat, my cat's name is betty

This is my monkey, my monkey's name is wukong

This is my dog, my dog's name is frank

This is my fish, my fish's name is george

This is my goat, my goat's name is adam

咱們能夠運用匹配來添加文本:

# 注意其中的/fish/a,這意思是匹配到/fish/後就追加一行

$ sed"/fish/a This is my monkey, my monkey's name is wukong"my.txt

This is my cat, my cat's name is betty

This is my dog, my dog's name is frank

This is my fish, my fish's name is george

This is my monkey, my monkey's name is wukong

This is my goat, my goat's name is adam

下面這個例子是對每一行都挺插入:

$ sed"/my/a ----"my.txt

This is my cat, my cat's name is betty

----

This is my dog, my dog's name is frank

----

This is my fish, my fish's name is george

----

This is my goat, my goat's name is adam

----

c命令

c 命令是替換匹配行

$ sed "2 c This is my monkey, my monkey's name is wukong" my.txt

This is my cat, my cat's name is betty

This is my monkey, my monkey's name is wukong

This is my fish, my fish's name is george

This is my goat, my goat's name is adam

$ sed"/fish/c This is my monkey, my monkey's name is wukong"my.txt

This is my cat, my cat's name is betty

This is my dog, my dog's name is frank

This is my monkey, my monkey's name is wukong

This is my goat, my goat's name is adam

d命令

刪除匹配行

$ sed'/fish/d'my.txt

This is my cat, my cat's name is betty

This is my dog, my dog's name is frank

This is my goat, my goat's name is adam

$ sed'2d'my.txt

This is my cat, my cat's name is betty

This is my fish, my fish's name is george

This is my goat, my goat's name is adam

$ sed'2,$d'my.txt

This is my cat, my cat's name is betty

p命令

打印命令

你能夠把這個命令當成grep式的命令

# 匹配fish並輸出,能夠看到fish的那一行被打了兩遍,

# 這是由於sed處理時會把處理的信息輸出

$ sed'/fish/p'my.txt

This is my cat, my cat's name is betty

This is my dog, my dog's name is frank

This is my fish, my fish's name is george

This is my fish, my fish's name is george

This is my goat, my goat's name is adam

# 使用n參數就行了

$ sed -n '/fish/p'my.txt

This is my fish, my fish's name is george

# 從一個模式到另外一個模式

$ sed -n '/dog/,/fish/p'my.txt

This is my dog, my dog's name is frank

This is my fish, my fish's name is george

#從第一行打印到匹配fish成功的那一行

$ sed-n '1,/fish/p'my.txt

This is my cat, my cat's name is betty

This is my dog, my dog's name is frank

This is my fish, my fish's name is george

相關文章
相關標籤/搜索