84669 人學習
152542 人學習
20005 人學習
5487 人學習
7821 人學習
359900 人學習
3350 人學習
180660 人學習
48569 人學習
18603 人學習
40936 人學習
1549 人學習
1183 人學習
32909 人學習
如果第1行和第2行都不以;开头,则合并这两行为新行,并继续处理新行和第3行; 如果第1行以;开头,则继续处理第2行和第3行。 以上流程仅为方便描述,只要能达到相同效果即可。 如输入为: ;a ;;b c d; e;;; ;f g 期望输出: ;a ;;b cd;e;;; ;f g
学习是最好的投资!
awk '!/^;/{a=arrreee}/^;/{if(a!="")print a;print rrreee;a="";}END{if(a!="")print a;}'
awk語法 test1{statements1}test2{statements2}...
test1{statements1}test2{statements2}...
針對每一行,若符合test1,則執行statement1,若滿足test2,執行statement2 ...
每一行
所以分3部分:
!/^;/{a=a;}
;
a
!/^;/
!
/.../
^;
a=a
/^;/{if(a!="")print a;print ;;a="";}
/^;/
if(a!="")print a;print ;a="";
if(a!="")print a;
print
a="";
END{if(a!="")print a;}
END
BEGIN
首先: 將換行符號去掉,/n//g 然後: 判斷字母序列右邊是否有數字,有則在右邊加上換行符/([a-z]+)(?=[0-9]+)/1/n/g 判斷字母序列左側是否有數字,有則在左側加上換行符/([a-z]+)(?<=[0-9]+)//n1/g 最後: 將上面正規表示式用sed或awk實現。
/n//g
/([a-z]+)(?=[0-9]+)/1/n/g
/([a-z]+)(?<=[0-9]+)//n1/g
sed
awk
awk版本
awk ' sed -n '/^;/{H;x;s/^\n//g;p;s/.*//g;x;};/^;/!{H;x;s/\n//g;x};${/^;/!p}' urfile !~ /^;/{a=arrreee;}/^;/{print a?a"\n"rrreee:rrreee;a=""}END{if(a)print a}' urfile
sed -n '/^;/{H;x;s/^\n//g;p;s/.*//g;x;};/^;/!{H;x;s/\n//g;x};${/^;/!p}' urfile
再附加一個sed的
這種略複雜的需求,用sed/awk是可以實現,但是我覺得不推薦,這時候一般用python或perl來做更有效率。
不過為了看看我的sed功底還在不在,還是試了一下,目前簡單測試沒有發現問題,程式碼如下:
sed -r -n '/^;/!{h;s/.*//;x;:l $!{H;n;/^;/!b l};x;s/\n//gp;g};p'
解釋幾個重點的部分: 1. h;s/.*//;x;是為了清空hold space 2. :l $!{H;n;/^;/!b l};部分是一個循環,將所有的非;開頭的行合併到hold space,退出條件有兩個:到達最後一行或遇到一個;開頭的行 3. x;s/n//gp;g 將hold space中的內容去掉換行符並列印出來 4. 最後p列印pattern space中的內容,用來列印;開頭的行
h;s/.*//;x;
:l $!{H;n;/^;/!b l};
x;s/n//gp;g
p
答案還沒寫完,發現一個bug了: 如果檔案的最後有2行以上的非;開頭的行,最後一行沒有被合併。
修改一下原來的答案為:
sed -r -n '/^;/!{h;s/.*//;x;:l $!{H;n;/^;/!b l};/^;/!{H;g;s/\n//gp;t};x;s/\n//gp;g};p'
修改說明: 1. 跳出迴圈之後,判斷目前行如果不是;開頭(根據先前的跳出條件可知,這是最後一行),將目前行加入hold space,然後處理hold space的內容
看吧,一個其實也不是很複雜的需求,用sed來寫,命令越寫越長,1個月後還能一眼看懂麼?這類需求還是不要用sed來做吧
答案
解釋
awk語法
test1{statements1}test2{statements2}...
針對
每一行
,若符合test1,則執行statement1,若滿足test2,執行statement2 ...所以分3部分:
!/^;/{a=a
如果不以;
}a
開頭,則將目前行追加到臨時變數(作為緩衝區)
!/^;/
!
/.../
^;
;
正規表示式,表示以a=a
a
a
/^;/{if(a!="")print a;print
;
;a="";}a
若以- 開頭,先輸出暫時拼接的變數
-
列印目前行
/^;/
(若有),再輸出目前行;
if(a!="")print a;print
;a="";
判斷目前行是否以
開頭-
;-
if(a!="")print a;
print
a="";
a
如果a不為空,則輸出a的值(print自動換行)END{if(a!="")print a;}
的值,以備下次使用a
;
a
處理完所有行,最後再判斷緩衝區;
中是否有內容,若有,則列印END
BEGIN
如果最後幾行都不以首先: 將換行符號去掉,
/n//g
然後: 判斷字母序列右邊是否有數字,有則在右邊加上換行符
/([a-z]+)(?=[0-9]+)/1/n/g
判斷字母序列左側是否有數字,有則在左側加上換行符
/([a-z]+)(?<=[0-9]+)//n1/g
最後: 將上面正規表示式用
sed
或awk
實現。awk版本
再附加一個sed的
rrreee這種略複雜的需求,用sed/awk是可以實現,但是我覺得不推薦,這時候一般用python或perl來做更有效率。
不過為了看看我的sed功底還在不在,還是試了一下,目前簡單測試沒有發現問題,程式碼如下:
解釋幾個重點的部分:
1.
h;s/.*//;x;
是為了清空hold space2.
:l $!{H;n;/^;/!b l};
部分是一個循環,將所有的非;
開頭的行合併到hold space,退出條件有兩個:到達最後一行或遇到一個;
開頭的行3.
x;s/n//gp;g
將hold space中的內容去掉換行符並列印出來4. 最後
p
列印pattern space中的內容,用來列印;
開頭的行答案還沒寫完,發現一個bug了: 如果檔案的最後有2行以上的非
;
開頭的行,最後一行沒有被合併。修改一下原來的答案為:
修改說明:
1. 跳出迴圈之後,判斷目前行如果不是
;
開頭(根據先前的跳出條件可知,這是最後一行),將目前行加入hold space,然後處理hold space的內容看吧,一個其實也不是很複雜的需求,用sed來寫,命令越寫越長,1個月後還能一眼看懂麼?這類需求還是不要用sed來做吧