2010-06-29 118 views
1

我必須處理各種輸入文件,其中包含許多字段,任意排列,但所有字段都一致地命名並標記爲標題行。這些文件需要重新格式化,以便所有需要的字段都按特定的順序排列,剝離不相關的字段並填充缺失的字段。我曾經希望用AWK來處理這個問題,因爲它在處理過去與場相關的困境時已經做得很好。使用AWK重新命名字段

有點擺弄周圍後,我結束了東西很像以下(從內存寫作,未經測試):

# imagine a perfectly-functional BEGIN {} block here 

NR==1 { 
    fldname[1] = "first_name" 
    fldname[2] = "last_name" 
    fldname[3] = "middle_name" 
    maxflds = 3 

    # this is just a sample -- my real script went through forty-odd fields 

    for (i=1;i<=NF;i++) for (j=1;j<=maxflds;j++) if ($i == fldname[j]) fldpos[j]=i 
} 

NR!=1 { 
    for (j=1;j<=maxflds;j++) { 
    if (fldpos[j]) printf "%s",$fldpos[j] 
    printf "%s","/t" 
    } 
    print "" 
} 

現在,這個解決方案工作罰款。我運行它,我得到我的輸出正是我想要的。那裏沒有投訴。然而,對於長度超過三個字段的任何內容(例如我必須使用的四十多個字段),這是很多令人痛苦的冗餘代碼,它總是會一直困擾着我。不得不在其他地方插入一個領域的想法讓我不寒而慄。

每當我看到它時,我都會死在裏面。

我敢肯定,那裏一定有更優雅的解決方案。或者,如果沒有,也許有更適合這種任務的工具。 AWK在它自己的領域是很棒的,但我擔心我可能會拉伸它是限制一些與此。

任何見解?

回答

0

我能想到的唯一建議是將初始數組設置移動到BEGIN塊中,並從循環中單獨的模板文件中讀取有序的字段名稱。那麼你的awk程序只包含沒有嵌入數據的循環。您的外部模板文件將是一個簡單的換行符分隔列表。

BEGIN {while ((getline < "fieldfile") > 0) fldname[++maxflds] = $0} 

當然,您仍然可以像現在一樣閱讀標題行。但是,我發現您可以使用關聯數組並將嵌套的for循環縮減爲單個for循環。喜歡的東西(未經測試):

BEGIN {while ((getline < "fieldfile") > 0) fldname[$0] = ++maxflds} 

NR==1 { 
    for (i=1;i<=NF;i++) fldpos[i] = fldname[$i] 
} 
+0

我喜歡的關聯數組的想法,但據我所知有保證這個數組的順序沒有乾淨的方式同時印刷,短從頭開始,因此寫了排序功能(不GAWK的無不幸的是)。我想''fldpos [fldname [$ i]] = i'在標題循環中可以工作,因爲它給了我一個整數鍵以在打印時循環... – goldPseudo 2010-06-29 15:19:46

+0

@goldPseudo:哎呀,我沒在想關於那個。我認爲你的想法可行。 – 2010-06-29 17:23:27