2010-04-30 22 views
3

試圖合併我有的一些數據。輸入看起來像這樣:awk/sed/shell合併/連接數據

foo bar 
foo baz boo 
abc def 
abc ghi 

而且我想輸出的樣子:

foo bar baz boo 
abc def ghi 

我使用一些陣列在shell腳本的一些想法,但我一直在尋找一個更優雅或更快的解決方案。

回答

3

如何加入?

file="file" 
join -a1 -a2 <(sort "$file" | sed -n 1~2p) <(sort "$file" | sed -n 2~2p) 

的SEDS還有剛剛分裂奇數和偶數行的文件

+0

靠近!我將不得不事先對數據進行排序(如果具有重複的第一個字段的記錄不是彼此相鄰的,則不起作用),並且它不會吐出沒有重複的字段(再次,這不是真的問題,這個一點命令做了我的情況的困難部分)。 謝謝! – Kyle 2010-04-30 23:37:38

+0

我已經爲你做了這樣的事情。如果你想顯示uniq項目,那麼用-a1 -a2來實現,我只是用 – pixelbeat 2010-04-30 23:46:30

+0

更新了答案。如果我沒有事先對文件進行排序,我仍然在輸出中得到一些重複項。但就像我說的那樣,這不是問題。 -a1 -a2解決了我的另一個問題。 (爲什麼我以前從未使用過連接?!)再次感謝。 – Kyle 2010-04-30 23:49:41

0

如果第一個字段的長度是固定的,則可以使用uniq-w選項。否則你晚上想要使用awk(警告:未經測試的代碼):

awk ' 
    BEGIN{last='';} 
    { 
     if ($1==last) { 
      for (i = 1; i < NF;i++) print $i; 
     } else { 
      print "\n", $0; 
      last = $1; 
     } 
    }' 
+0

第一字段的長度也可以變化,並我不認爲uniq具有我正在尋找的功能(將額外字段連接到一行上) – Kyle 2010-04-30 23:16:16

2

雖然pixelbeat的答案的作品,我不能說我對此非常熱情。我想我會用awk是這樣的:

{ for (i=2; i<=NF; i++) { lines[$1] = lines[$1] " " $i;} } 
END { for (i in lines) printf("%s%s\n", i, lines[i]); } 

這不應該需要預先對數據進行排序,並應做工精細,無論字段的數量或長度(短溢出內存,當然)。它唯一明顯的缺點是它的輸出是任意的順序。如果你需要排序,你需要通過排序來輸出輸出(但回到原來的順序是別的)。

+0

我真的很喜歡這個解決方案,更精簡一點。謝謝! – Kyle 2010-05-02 04:47:41

2

一個AWK溶液

awk ' 
    {key=$1; $1=""; x[key] = x[key] $0} 
    END {for (key in x) {print key x[key]}} 
' filename 
0

純擊,對於真正的交替行:

infile="paste.dat" 

toggle=0 
while read -a line ; do 
    if [ $toggle -eq 0 ] ; then 
    echo -n "${line[@]}" 
    else 
    unset line[0]    # remove first element 
    echo " ${line[@]}" 
    fi 
    ((toggle=1-toggle)) 
done < "$infile" 
0

基於FGM的純擊snippet

text=' 
foo bar 
foo baz boo 
abc def 
abc ghi 
' 

count=0 
oneline="" 
firstword="" 
while IFS=" " read -a line ; do 
    let count++ 
    if [[ $count -eq 1 ]]; then 
     firstword="${line[0]}" 
     oneline="${line[@]}" 
    else 
     if [[ "$firstword" == "${line[0]}" ]]; then 
     unset line[0] # remove first word of line 
     oneline="${oneline} ${line[@]}" 
     else 
     printf "%s\n" "${oneline}" 
     oneline="${line[@]}" 
     firstword="${line[0]}" 
     fi 
    fi 
done <<< "$text"