linux - shell怎么多行并作一行处理?
PHPz
PHPz 2017-04-17 12:05:30
0
4
815

如果第1行和第2行都不以;开头,则合并这两行为新行,并继续处理新行和第3行;
如果第1行以;开头,则继续处理第2行和第3行。
以上流程仅为方便描述,只要能达到相同效果即可。
如输入为:
;a
;;b
c
d;
e;;;
;f
g
期望输出:
;a
;;b
cd;e;;;
;f
g

PHPz
PHPz

学习是最好的投资!

全部回覆(4)
大家讲道理

答案

awk '!/^;/{a=arrreee}/^;/{if(a!="")print a;print rrreee;a="";}END{if(a!="")print a;}'

解釋

awk語法 test1{statements1}test2{statements2}...

針對每一行,若符合test1,則執行statement1,若滿足test2,執行statement2 ...

所以分3部分:

  • !/^;/{a=a;} 如果不以a開頭,則將目前行追加到臨時變數
    (作為緩衝區)
    • !/^;/

      • !
      • 否定
      • /.../
      • 表示測試目前行是否滿足給定正規表示式
      • ^; ; 正規表示式,表示以
      • 開頭
    • a=a

      • a
      • 變量,無聲明,直接使用,預設值是0、null、"",根據使用場景自動轉換,這裡第一次用就是空字串
      • 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
最後: 將上面正規表示式用sedawk實現。

Peter_Zhu

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的

rrreee
PHPzhong

這種略複雜的需求,用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中的內容,用來列印;開頭的行

答案還沒寫完,發現一個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來做吧

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!