標籤:

sed之同一特徵的行合併成一整行

文本:sadasdstartpoint:xxxxxxendpoint:xxxxxpath:xxxxslack:xxxxjccjpath:xxxxzistartpoint:xxxxxxendpoint:xxxxx要求把含有冒號的連續的多行合併成一行,以空格分割:sadasdstartpoint:xxxxxx endpoint:xxxxx path:xxxx slack:xxxxjccjpath:xxxxzistartpoint:xxxxxx endpoint:xxxxx

  1. sed "/:/{:a;N;/
    [^:]*$/!{$!ba};s/
    ([^:]*:)/ 1/g}" file

[解析] 一開始這問題還有點小棘手,思考再三定下覺得正確的思路後慢慢寫,最後還是搞定了。把匹配到冒號的行開始執行死循環,一直用 N 讀取下一行,直到讀到沒有冒號的行,或者讀到尾行,才開始替換,把換行替換成空格,這樣跳出死循環後,命令執行完了sed會把結果輸出。這是總體的思路,細節上幾個注意的地方,第一:匹配不包含冒號的行,注意後面加上 $ 邊界,表示文本末尾,否則的話前面 pattern space 內的內容也匹配到,sed就會去執行替換,從而失敗。第二,如果只是全局替換
為空格,那麼會把最後那行不包含冒號的行也會被替換到同一行內,所以這裡要排除最後一個
後不包含冒號內容。第三,用N讀取到最後一行,發現沒匹配到冒號它又會再次死循環ba跳去N讀取下一行,發現沒有行可以讀取的時候N會中止命令直接結束,那麼就不會有後面的替換操作,為了避免這種情況,必須加上尾行的判斷,把ba跳轉排除尾行。

  1. sed "/:/{:a;N;/:[^
    ]*$/s/
    / /;ta;P;D}" file

[解析] 這個命令就要短很多了,我老是忘了我們的老朋友,P;D 組合。匹配到冒號的行後,N讀取下一樣內容,然後嘗試替換,如果下一行也是有冒號的行,那麼冒號後面到 $ 結束就不會有換行符,替換會成功,ta 跳轉去Table a處,又讀取下一行,直到讀取到不含有冒號的行,那麼匹配就會失敗,因為該行不含有冒號,正則會匹配到上一行的冒號,那樣的話後面必然會出現一個換行符了,所以替換失敗,ta不會生效,這時候執行後面的 P 列印 pattern space 的第一行,也就是把含有冒號的行處理為了一整行的那一行,然後 D 刪除pattern space 的第一行。這時候pattern space 留下的是 "jccj" 這樣的內容,那麼 D 會跳轉命令去行首繼續執行,這時候不匹配冒號"jccj" 就被輸出到了屏幕,然後繼續後面的操作。

  1. awk "/:/{i=i?i FS $0:$0;next}{print i?i RS $0:$0;i=0}END{if(i)print i}" file

[解析] 其實awk執行流程更符合我們的編程思維,匹配到冒號的行,就把各行用 FS 空格接起來,直到沒有匹配到冒號然後列印出來,並把i變數置零。最後END再判斷一下,如果i有內容就列印。

  1. awk "ORS=/:/?FS:RS;END{printf RS}" file

[解析] 這個就不說了,秒殺。
推薦閱讀:

漢獻之孱弱、劉禪之痴呆、楊廣之荒淫,合併成一人,你知道他是誰
段子手們眼中的央企合併是怎麼樣的?
小腸腹股溝疝合併腸梗阻
糖尿病合併高血壓,如何選擇降壓藥?
糖尿病患者要控制血糖, 這6類食物千萬要少吃。否者有合併症危險

TAG:特徵 | 合併 |