2015-06-09 22 views
0

例子:的grep/SED用空格代替敵不過我在greping信息的文件的

name : server1 
description : webserver 
memory : 32gb 

name : server2 
memory : 128gb 

name : server3 
description : appserver 

我在做這樣的事情:

cat myfile | egrep -w "name|description|memory" | awk -F" " '{print $3}' >> myfile2 

爲了找回來自myfile中第二列的信息。

然後,我將myfile2格式化爲在每行上都有來自每個服務器的信息(使用tr替換CRLF),並用分號分隔以將它們導入到Excel中。

myfile2: 
server1;webserver;32gb 
server2;128gb 
server3;appserver 

問題是:當egrep的不匹配任何東西(如說明對服務器2或內存服務器3),有在myfile2一行的差距......我怎樣才能用空格代替它?

輸出希望我的文件2的:
server1的; Web服務器; 32GB
服務器2 ;; 128GB
server(服務器);應用服務器;;

+1

你可以[編輯]你的問題,告訴我們你所顯示的輸入究竟是什麼樣的輸出? –

+2

這聽起來像一個[XY問題](http://mywiki.wooledge.org/XyProblem)。你在這裏試圖做什麼,以及會消耗這些數據的是什麼?正如湯姆建議的那樣,請提供您正在尋找的輸出變體的示例。 – ghoti

+0

'grep -v「^ $」'將排除空白行。 – Sobrique

回答

1

我沒有看到需要在輸入數據上使用grepawk命令幾乎可以執行grep可以執行的任何操作。考慮以下幾點:是

awk -F' *: *' ' 
    { 
    a[$1]=$2; 
    } 

    /^memory/ { 
    printf("%s;%s;%s\n", a["name"], a["description"], a["memory"]); 
    delete a; 
    }' myfile 

的在這裏組成部分如下:

  • -F...套字段定界符,包括空格。
  • a[$1]=$2用來自每條記錄的數據填充一個短期數組。
  • /^memory/只對每個組的最後一行執行這個食譜...
  • printf(...)顯示你的輸出,並
  • delete a讓你開始下多行記錄新鮮。

你當然可以壓縮這一切都成一條線:

awk -F' *: *' '{ a[$1]=$2 } /^memory/ { printf("%s;%s;%s\n", a["name"], a["description"], a["memory"]); delete a }' myfile 

這是你需要什麼?

UPDATE

我看到你已經修改了你的問題,包括是從不同的樣本數據上面什麼支持的解決方案。下面是應與當前的例子工作的最新情況:

function outp() { 
     printf("%s;%s;%s\n", a["name"], a["description"], a["memory"]); 
} 

BEGIN { 
     seen=0; 
     FS=" *: *"; 
} 

/^name/ && seen { 
     outp(); 
     delete a; 
} 

/^name/ { 
     seen=1; 
} 

{ 
     a[$1]=$2; 
} 

END { 
     outp(); 
} 

該應用功能(outp())把事情簡單化。它使用seen變量來確定腳本是否已經看到任何實際數據(否則,/^name/的第一個匹配將生成空輸出)。並且它繼續使用a數組來收集重要的字段。

需要注意的是現在,而不是假定你將有一個「記憶」在每一個記錄的年底的是很重要的,我們假設你在開始每個記錄有「名」 。如果這個假設是錯誤的,請說明你認爲你應該如何分辨彼此的記錄(例如,哪裏停止,哪下一個開始)。例如,空白行是一個選項。

+0

它工作正常,謝謝! – tonio94

+0

我更新了我的答案以反映您問題中的更新示例數據。 – ghoti

2

這聽起來像所有你需要的是:

$ awk -v RS= -F' *: *|\n' -v OFS=';' '{print $2,$4,$6}' myfile 
server1;webserver;32gb 
server2;;128gb 

如果你想CRLF行結束,然後就告訴awk中,通過在前面加-v ORS='\r\n'

不知道爲什麼你不只是更新你的問題還沒有,但它聽起來好像這是你真正需要的:

$ cat file 
name : server1 
description : webserver 
memory : 32gb 

name : server2 
memory : 128gb 

name : server3 
description : appserver 

$ cat tst.awk 
BEGIN{ 
    RS="" 
    FS=" *: *|\n" 
    OFS=";" 
    numNames = split("name description memory",names,/ /) 
    for (i=1; i<=numNames; i++) { 
     name2nr[names[i]] = i 
    } 
} 
{ 
    delete vals 
    for (i=1;i<=NF;i+=2) { 
     vals[name2nr[$i]] = $(i+1) 
    } 
    for (i=1; i<=numNames; i++) { 
     printf "%s%s", vals[i], (i<numNames?OFS:ORS) 
    } 
} 

$ awk -f tst.awk file 
server1;webserver;32gb 
server2;;128gb 
server3;appserver; 

可以書面補充說,剛剛計算出的字段名第一遍而不是硬編碼他們在BEGIN部分,但隨後場的輸出順序變得依賴它們出現的順序在這種情況下,輸入不確定是否值得。

+1

這也適用。 :-) +1爲簡潔起見。 – ghoti

+0

謝謝,這聽起來不錯:)但是,我在我的例子中犯了一個錯誤。事實上,當沒有數據時,該字段被隱藏。 所以對於server2: 'name:server2 memory:128gb' 在沒有描述server2的情況下。 這就是爲什麼我要開始grep。因爲在你的例子中,打印$ 4變成「128gb」時,對於另一臺服務器來說就是描述。 – tonio94

+0

對不起,我不知道你是什麼意思,當沒有數據的領域是隱藏的。如果您的示例不正確或不完整,請編輯您的問題以提供更好的示例。 –

相關問題