sed的N;P用法

原文地址

這裡介紹的是sed的一個多行模式的使用,一開始對sed中命令N的用法不是很理解,經過多次嘗試,通過幾個例子對N的用法進行總結:

N即Next,它同n(next)的區別是:N命令將下一行追加到模式空間中,不列印模式空間的值,而使用n是列印當前模式空間的內容,並且讀取下一行

蒙受啟發
> cat num
1
2
3
4
5
6
7
8
9
> sed ’N;$!D’ num
8
9
> 執行過程詳解: 首先解釋重要的幾個命令的用途: D刪除模板塊的第一行 並返回指令碼頭部執行 $ 錨定行的結束 如:/sed$/匹配所有以sed結尾的行 ,繼續執行 ! 表示後面的命令對所有沒有被選定的行發生作用。
大概說一下:
N;$!D
首先讀入第一行: 1 (注:這不是N命令讀入的)
執行N,讀入第2行,追加到1後面,成了1\n2;
$!D,不是最後一行,所以執行D,模式空間由1\n2成了2, 控制流返回指令碼第一條命令,即N。這樣一直執行
….
直到執行N讀入第9行:9,這裡模式空間為:8\n9
$!D,因為是最後一行,所以不執行D,控制流到達指令碼底部,輸出模式空間的內容:
8
9 上面這段例子摘自網路,給了我很大啟發,另外測試如下: 關於N: append the next line of input into the pattern space. 這是sed使用者手冊當中說的,很明顯,意思是將當前讀入行的下一行讀取到當前的模式空間。 關於P: Print up to the first embedded newline of the current pattern space.列印當前模式空間中的第一塊。 關於D: Delete up to the first embedded newline in the pattern space. Start next cycle, but skip reading from the input if there is still data in the pattern space. 刪除當前模式空間的第一塊,重新開始下一次迴圈,這個在後面例子中給予驗證: 各種驗證
驗證一:NP結合 > cat num
1
2
3
4
> sed ’N;P’ num
1
1
2
3
3
4 > sed ’N;p’ num
1
2
1
2
3
4
3
4 對於上面的結果給予解釋:P用於列印當前模式空間的第一塊,而p列印整個當前模式空間。所以當使用P的時候,步驟如下:首先sed預設的讀取1,模式空間為1,讓你後執行N,模式空間變成1\n2\n,然後執行P,也就是列印1\n;當前行的處理,列印模式空間也就是1\n2\n;這時sed再從檔案中讀取下一行,也就到了3\n,執行N;模式空間變成了3\n4\n; 執行P;列印3\n;繼續執行當前行的處理,列印模式空間3\n4\n;sed再從檔案中讀取下一行,發現沒有了,結束處理流程。對於小p,和d大P的區別瞭解的話也就不難理解了。 驗證二:ND結合 > cat num
1
2
3
4
> sed ’N;D’ num
4
> sed ’N;d’ num
> 對於D;刪除當前模式空間第一塊,並且返回命令開始繼續執行。上述結果解釋如下: 首先sed讀取一行1\n;執行到N;模式空間為1\n2\n;執行D;模式空間變為:2\n;跳到前面繼續執行N;模式空間變為2\n3\n;執行D;模式空間變為:3\n;跳回繼續執行N;模式空間變為:3\n4\n;接著執行D;模式空間變為:4\n;跳回執行N的時候發現沒有了下一行,所以跳出迴圈,接著sed繼續處理,列印4\n;sed繼續再讀取檔案的時候沒有資料,所以結束處理。 驗證3:NpD,再驗證 > cat num
1
2
3
4
> sed ’N;p;D’ num
1
2
2
3
3
4
4 首先,sed讀取一行,執行到N;模式空間為:1\n2\n;執行p;列印1\n2\n;執行D;模式空間變為:2\n;跳回執行N;模式空間變為:2\n3\n;執行p;列印2\n3\n;執行D;模式空間變為:3\n;跳回執行N;模式空間變為:3\n4\n;執行p;列印3\n4\n;執行D;模式空間變為:4\n;跳回執行N;沒有資料。跳出迴圈,sed繼續處理,預設列印模式空間所有資料4\n; 因此只有1列印一遍,其餘行都列印2遍。 另外d和大D的區別瞭解以後也就明白了。 總結體會:sed處理始終在一個模式空間中進行,而且對於待處理檔案,N讀取了檔案中的一行後,sed繼續處理的時候應該是接著去讀取,這裡我理解是sed讀取檔案和N讀取檔案這些的共用一個指標。 在sed處理檔案的時候,每一行都被儲存在一個叫模式空間的臨時緩衝區中,除非行被刪除或者輸出被取消,否則所有被處理的行都將 列印在螢幕上。接著模式空間被清空,並存入新的一行等待處理。 常用命令: 利用sed給每行新增行號。 > cat passwd uucp:x:10:14:Unix-to-Unix CoPy system:/etc/uucp:/bin/bash
mqq:x:1000:100::/usr/local/app:/bin/bash
mysql:x:1001:1001::/home/mysql:/bin/bash
natpan:x:1002:100::/data/natpan:/bin/bash
nagios:x:1003:100::/home/nagios:/bin/bash
nagios:x:1003:100::/home/nagios:/bin/bash
nagios:x:1003:100::/home/nagios:/bin/bash
給每行加上行號,命令如下:
> sed = passwd | sed ’N;s/\n/: /g’
1: uucp:x:10:14:Unix-to-Unix CoPy system:/etc/uucp:/bin/bash
2:
3: mqq:x:1000:100::/usr/local/app:/bin/bash
4: mysql:x:1001:1001::/home/mysql:/bin/bash
5: natpan:x:1002:100::/data/natpan:/bin/bash
6: nagios:x:1003:100::/home/nagios:/bin/bash
7: nagios:x:1003:100::/home/nagios:/bin/bash
8: nagios:x:1003:100::/home/nagios:/bin/bash
mqq@wsd_207_62_sles10sp1:~/alenzhou/shell_test/sed>
空行不列印行號,做一下匹配就行
> sed ’/./=’ passwd | sed ’/./N;s/\n/: /g’
1: uucp:x:10:14:Unix-to-Unix CoPy system:/etc/uucp:/bin/bash
3: mqq:x:1000:100::/usr/local/app:/bin/bash
4: mysql:x:1001:1001::/home/mysql:/bin/bash
5: natpan:x:1002:100::/data/natpan:/bin/bash
6: nagios:x:1003:100::/home/nagios:/bin/bash
7: nagios:x:1003:100::/home/nagios:/bin/bash
8: nagios:x:1003:100::/home/nagios:/bin/bash