2014-04-01 64 views
1

根據前幾個字符是否爲空,我可以在上一行追加一行嗎?如何根據第一個字段是否爲空來連接相鄰的行?

例如,我有以下數據:

zone: z_ABCSVR01_STORAGE1 
       ABCSVR; STORAGE1_P1; 
     STORAGE_P2 
zone: z_SUNSVR1_NBUSANCP 
       SUNSVR1; NBUSANCP; 
zone: z_WINSVR01_STORAGE2 
       WINSVR01; STORAGE1_P2; 
     STORAGE_P3 

我需要下面的輸出:

z_ABCSVR01_STORAGE1 ABCSVR; STORAGE1_P1; STORAGE_P2      
z_SUNSVR1_NBUSANCP SUNSVR1; NBUSANCP;    
z_WINSVR01_STORAGE2 WINSVR01; STORAGE1_P2; STORAGE_P3  

回答

2

使用AWK

awk '{printf (/^zone/)?RS $0:FS $0}' file 

zone: z_ABCSVR01_STORAGE1     ABCSVR; STORAGE1_P1;   STORAGE_P2 
zone: z_SUNSVR1_NBUSANCP     SUNSVR1; NBUSANCP; 
zone: z_WINSVR01_STORAGE2     WINSVR01; STORAGE1_P2;   STORAGE_P3 

awk '{printf (/^[[:space:]]/)?FS $0:RS $0}' file 

如果您需要刪除無用的空白:

awk '{printf (/^zone/)?RS $0:FS $0}' file|awk '$1=$1' 

zone: z_ABCSVR01_STORAGE1 ABCSVR; STORAGE1_P1; STORAGE_P2 
zone: z_SUNSVR1_NBUSANCP SUNSVR1; NBUSANCP; 
zone: z_WINSVR01_STORAGE2 WINSVR01; STORAGE1_P2; STORAGE_P3 
+0

刪除空格:awk'{$ 1 = $ 1; printf(/^zone /)?RS $ 0:FS $ 0}'file' – Jotne

+0

對於關鍵字'/^zone /',這個命令是精細。但是,如果按照「前幾個字符爲空」的規則進行處理,則不能 – BMW

4

這裏是另一種方式,如果你有GNU awk

$ awk -v RS='zone:' '$1=$1' file 
z_ABCSVR01_STORAGE1 ABCSVR; STORAGE1_P1; STORAGE_P2 
z_SUNSVR1_NBUSANCP SUNSVR1; NBUSANCP; 
z_WINSVR01_STORAGE2 WINSVR01; STORAGE1_P2; STORAGE_P3 
+2

「NR> 1」的用法是什麼? 'awk -v RS ='zone:''$ 1 = $ 1'file'很好 – BMW

+0

不,在我的env(CYGWIN)中,我沒有看到空行。 – BMW

+2

@BMW是正確的,'{$ 1 = $ 1} 1'將打印空白行,但是「$ 1 = $ 1」並不是因爲這隱式地也會在布爾上下文中評估「$ 1」,例如, '$ 1 {$ 1 = $ 1; print}'(這是我的理解)。 –

0
sed -n '1h;1!H;${x;s/\n *//g;p;}' YourFile 

也消除白色空間時,線結合

0

如果GNU awk是可用的,@ jaypal的簡潔和優雅的解決方案是要走的路。

這裏有一個兼容POSIX 解決方案,試圖點綴我的和交叉的T的(是什麼讓@ jaypal的解決方案不符合的是使用含有一種以上(文字)字符的RS(記錄分隔符)值):

  • 它消除zone:從輸出,作爲請求由OP
  • 它不會在開始打印一個額外\n或省略了後一個。
  • 它安全地使用printf,使用格式參數,以避免意外控制字符。擴大輸入線。
 
awk '{ 
     if ($1=="zone:") { sep=(notFirst++ ? ORS : ""); $1=""; $0=substr($0,2) } 
     else    { sep=OFS; $1=$1; } 
     printf "%s%s", sep, $0 
    }  
    END { print } 
    ' file 

這是同樣的程序的大量註釋版本,希望能解釋的awk這裏使用的更神祕的特點:

 
awk ' 
    { 
    if ($1=="zone:") { # Zone lines    
     # Determine the separator to *precede* the output line: 
     # ORS, the output *record* separator, which defaults to \n 
     # - unless it is the very first line. 
     # Net effect: zone lines start new output lines. 
     sep=(notFirst++ ? ORS : ""); 
     # Remove the `zone:` field by setting the first field, 
     # $1, to an empty string. 
     # Note: This causes the entire line to be rebuilt by joining the 
     #  fields with OFS, the output field separator, which defaults 
     #  to a space. Multiple adjacent space chars. are folded into 
     #  one in the process. 
     $1=""; 
     # Remove the space char. at the beginning of the rebuilt 
     # line that stems from setting $1 to an empty string. 
     $0=substr($0,2) 
    } else {   # Non-zone lines 
     # Determine the separator to *precede* the output line: 
     # just the regular output *field* separator (space), 
     # effectively causing this line to be appended to the 
     # previous one. 
     sep=OFS; 
     # Trigger rebuilding the line so as to fold 
     # multiple adjacent space chars. into one. 
     $1=$1; 
    }  
     # Output the separator followed by the rebuilt line. 
    printf "%s%s", sep, $0 
    } 
    # Since the `printf` statement above never outputs 
    # a *terminating* \n, we output one at the very end. 
    END { print } 
    ' file 
0

這可能會爲你工作(GNU SED):

sed ':a;$!N;/\nzone:/!s/\n\s*/ /;ta;s/^zone:\s*//;P;D' file 
相關問題