2016-01-14 77 views
3

我有數據列表,按以下格式:SED/AWK合併對線成一條線

Joined  : a 
Whatever  : b 
Last visited : c 
Useful  : y 
NotUseful1 : f 
Email  : z 
RandomWat : g 
*** end *** 
Joined  : a 
Whatever  : b 
Last visited : c 
Useful  : y 
NotUseful1 : f 
Email  : z 
RandomWat : g 
*** end *** 
Joined  : h 
Whatever  : i 
Last visited : j 
Useful  : k 
NotUseful1 : l 
Email  : m 
RandomWat : n 

我要的是:

Useful, Email, Joined, Last Visited 
y,z,a,c 
y,z,a,c 
k,m,h,j 

我可能已經有一個啤酒太多了,但我無法弄清楚如何在超長列中獲得跨線的值。有效的CSV格式的一些具體產出。

真的,我在找sed/awk中的東西,儘管任何文本處理器都可以。

+1

是否有多條記錄?如果是這樣,他們是如何分開的? – dawg

+0

但是你的領域是通過換行符分開的,不是嗎?空行? – dawg

+0

編輯的問題有點清晰..希望.. – jacob21

回答

3

您可以將Awk的記錄分隔符設置爲**end**並通過一些輕分析來區分這些字段;但如果格式是完全穩定的一系列的八條線以固定的順序,你真正需要的是

awk -F ' *: *' -v OFS=, '{i=NR%8; a[i]=$NF } 
    i==7 { print a[4], a[7], a[1], a[3] }' file 

如果值可能包含一個冒號,你將需要適應 - 這個簡單的代碼只是翻出最後結腸後的東西。

添加CSV標題留作練習(或者不要)。

-F選項設置輸入字段分隔符,所以Awk會將冒號分隔線,修剪任何相鄰的空格。 OFS是輸出字段分隔符;我們希望輸出逗號分隔。 NR是當前輸入行號,% 8計算模數;所以i的值從1到7,然後回到零,並開始再次攀登,在整個文件中重複。現在,我們使用i作爲數組a的索引,並將每行的最後一個字段收集到此數組中。當我們到達索引7時,我們有我們需要的所有領域,所以我們打印它們。 (我原本是0,但之後會失去最後一條記錄,因爲您的樣本數據中沒有終止**end**。)

NF是輸入字段的數目,我們預計這基本上是2所有的時間,所以我可以在那裏硬編碼$2。如果你需要延長這一點,我會完全忘記-F ' *: *'和手動sub("^[^:]*: *", ""),然後在$0具有整個值。

2

如果我理解正確,您希望在一行上打印第1列的全部內容,然後在下面的第二行打印相應的信息。

使用awk這非常簡單。

awk '{ORS=" "} {print$1}' file.txt 
awk '{ORS=" "} {print$NF}' file.txt 

輸出:

joined whatever last useful notuseful randomwat 
a b c y f z g 

ORS是輸出記錄分隔符。默認值是換行符。但在這種情況下,我們正在把它作爲一個空間。

因此,對於每一行awk將打印由空格分隔的每行的第一個字段。

然後,我們只需執行相同的命令,但使用最後一個字段而不是第一個字段。然後這將打印出下一行的相應信息,每個記錄再次以空格分隔。

如果你想讓你的新列成爲一個固定的寬度,我建議使用printf,但我相信還有其他方法可以做到這一點(我聽說Perl很擅長這一點)。

printf抑制換行符,所以我們可以刪除awk的ORS部分。 然而,由於換行永遠不會被創建,我們必須追加結束語句,每個awk命令後單獨printf命令讓我們到一個新的行,即

awk '{printf "%10s",$1}END{printf"\n"}' file.txt 
awk '{printf "%10s",$NF}END{printf"\n"}' file.txt 

這將打印列10用awk語句找到的所有內容都需要字符。

輸出:

joined whatever  last useful notuseful  email randomwat 
    a   b   c   y   f   z  g 

:AWK決定了每列是基於空間。因此,在您的示例中,「上次訪問」只會打印出最後一列,因爲這是第一列。如果您想要將多個單詞分組到特定列中,請將該單詞集合用引號""包裝。

+0

更新,如果你需要這個來執行相同的想法,但是對於不同的記錄集(看起來你有三個樣本),可以使用grep或sed命令分別抓取每條記錄,然後將它傳遞給awk。 – Xentrees

0

我不認爲awk是這項工作的最佳工具,或者我只是不瞭解awk的某些方面,這會讓這更容易。

awk 'BEGIN{split("4,6,1,3",x,",");i=1;FS=":"} 
    function s(e){gsub(/(*$)|(^ *)/,"",e);return e} 
    function p(a){for(j=1;j<length(x);++j)printf "%s,",a[x[j]];print a[x[j]]} 
    function e(){if(!d){p(h);d=1}p(v);i=1} 
    {if(NF==1)e();else{if(!d)h[i]=s($1);v[i++]=s($2)}} 
    END{e()}' infile.txt 

這不是太優雅,但是這種眼神就是做這份工作。您還可以修改"4,6,1,3"以選擇以csv格式打印哪些字段。
對於你的示例中,該輸出以下:

Useful,Email,Joined,Last visited 
y,z,a,c 
y,z,a,c 
k,m,h,j 

此命令要求所有條目具有相同的字段,鍵和值由:分離,並且條目由不包含冒號任何線分開。

我知道我遲到了,但我很想聽聽你是否想出了一個更好的解決方案來解決這個問題。