Linux sed的原理和用法

什麼是sed?

sed是一種非交互式流式編輯器,這裏有兩個關鍵字,非交互式和流式
非交互式就是指sed只能夠在命令行下輸入編輯命令來對文本進行編輯,然後在屏幕上查看輸出。
流式是指sed每次只從文件中讀入一行,然後對該行進行指定的處理,並將處理結果輸出到屏幕上,處理完後在讀入下一行。
sed對文本的過程處理如下:
(sed的原理.png)

sed的使用

命令格式

sed     [options]   'comandstring' file
sed     [options]   -f  script file
//script表示需要對輸入執行的一個或者多個操作指令。

相關選項

-e:表示以選項中指定的script來處理輸入的文件,也就是可以對輸入執行多條指令的意思。
-f :表示以選項中的script文件來處理輸入的文本文件,也就是把sed指令可以寫在文件中。
-n:表示僅僅顯示sed的command處理完後的結果。

相關命令

a:表示在當前行下面插入文本。
i :表示在當前行的上面插入文本。
c:表示把選定的行改爲新的文本。
d:表示刪除經過pattern匹配所選中的行。
D:表示刪除模式空間中的第一行。
s:表示替換指定的字符。
p:表示打印模式空間中的所有行。
P:表示只打印模式空間中的第一行。
q:表示退出sed。
b label:表示跳轉到腳本中帶有標記label的地方,如果標記不存在則跳轉到腳本的末尾。
r  file:表示從file中讀取一行。

sed的使用實例

好了,上面講解了sed的命令格式、參數和命令,下面我們來開始進行實戰,對上面的參數和命令來進行測試

指定執行行的地址的範圍(定址)

sed可以對單行或者多行進行處理,如果sed命令前面不指定地址範圍,那麼會默認匹配所有行。

**命令格式:**sed n1[,n2] {sed-command}
其中n1和n2代表行號,可以直接指定數字,或者通過正則表達式來進行匹配。

對指令進行測試的文本如下:

[lzh@leap_ sed_test]$ cat test.c 
#include<stdio.h>

int main()
{
    start
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    end
    return 0;
}

1.首先我們想打印這段文本的第3-第7行:

sed     '3,7p'      test.c

結果如下:

#include<stdio.h>

int main()
int main()
{
{
    start
    start
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    end
    return 0;
}

這裏我們發現3-7行打印了兩次,而其餘行只打印了一次,因爲sed編輯器默認對命令執行完畢後的處理動作就是打印,而我們在命令字符串中又指定了3-7行再打印一次,所以就會出現上面那種情況;同時這種情況還驗證了sed對文本的處理是一行一行進行的,因爲3-7行的重複打印了兩次。

如果在這裏我們只想打印sed命令處理過的行,那麼我們就需要使用-n選項了

sed     -n      '3,7p'      test.c

執行的結果如下:

[lzh@leap_ sed_test]$ sed -n '3,7p' test.c 
int main()
{
    start
    printf("Hello,World\n");
    printf("Hello,World\n");

2.現在我們來驗證一下用正則表達式來進行定址。
我們就把start到end之前的行打印出來吧。

sed     -n      '/start/, /end/p'       test.c
[lzh@leap_ sed_test]$ sed -n '/start/,/end/p' test.c
    start
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    printf("Hello,World\n");
    end

這裏因爲,和p都有特殊含義,所以我們需要對其用/進行轉義。


通過set對文本進行替換

相關command

/pattern/s/pattern1/pattern2/

/pattern/s/pattern1/pattern2/g

其中,/後面沒有帶g的表示只把通過pattern匹配到的行的第一個pattern1替換成pattern2。
帶g的表示把通過pattern匹配到的行中所有的pattern1替換成pattetn2。

1.我們還是用上面的文本把,這裏我們把start-end之間的printf全部都註釋掉。

[lzh@leap_ sed_test]$ sed -n '/start/,/end/s/printf/\/\/printf/p' test.c 
    //printf("Hello,World\n");
    //printf("Hello,World\n");
    //printf("Hello,World\n");
    //printf("Hello,World\n");
    //printf("Hello,World\n");
    //printf("Hello,World\n");

如果想讓註釋在文本中生效,我們可以指定-i選項。

2.下面我們來看看加g和不加g的區別吧。

[lzh@leap_ sed_test]$ cat file
111111111111
222222222222
333333333333
444444444444
222222222222
[lzh@leap_ sed_test]$ sed -n '/2/s/2/~2~/p' file
~2~22222222222
~2~22222222222
[lzh@leap_ sed_test]$ sed -n '/2/s/2/~2~/gp' file
~2~~2~~2~~2~~2~~2~~2~~2~~2~~2~~2~~2~
~2~~2~~2~~2~~2~~2~~2~~2~~2~~2~~2~~2~

應該可以看出來區別的吧~


sed的高級用法

要說sed的高級用法我們就不得不要說一下sed中的兩塊空間了
模式空間(pattern space):表示一個緩衝區,sed讀到的數據只能在模式空間裏面進行相應的處理。
保持空間(hold space):僅僅表示一個緩衝區,數據只是暫時存放在保持空間中,另外保持空間中默認有一個空行。

下面我們來說一下這兩個空間有關的參數吧:
g:將保持空間中的內容拷貝到模式空間中,原來模式空間中的內容被清除。
G:將保持空間中的內容append到模式空間中。
h:將模式空間中的內容拷貝到保持空間中。
H:將模式空間中的內容追加到保持空間中。
d:刪除模式空間中的所有行,並讀入下一行到pattern中。
D:刪除多行模式空間中的第一行,不讀入下一行。
x:交換保持空間和模式空間的內容。
N:以追加方式將文本內容讀取到模式空間中。

## 使用案例

1.我們將列序列轉化成行序列。

[lzh@leap_ sed_test]$ seq 10
1
2
3
4
5
6
7
8
9
10
[lzh@leap_ sed_test]$ seq 10 | sed -n 'H;${x;s/\n/ /g;p}'
 1 2 3 4 5 6 7 8 9 10
  1. 我們倒序輸出序列。
[lzh@leap_ sed_test]$ seq 10
1
2
3
4
5
6
7
8
9
10
[lzh@leap_ sed_test]$ seq 10 | sed -n '1!G;h;$!d;p'
10
9
8
7
6
5
4
3
2
1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章