2009-09-08 22 views
3

我有一些來自遺留系統的數據文件,我想使用Awk進行處理。每個文件都由一系列記錄組成。有幾種不同的記錄類型,每種記錄類型都有一組不同的固定寬度字段(沒有字段分隔符)。記錄的前兩個字符表示類型,由此您知道哪些字段應該遵循。一個文件可能是這個樣子:使用Awk處理文件,其中每個記錄具有不同的固定寬度字段

AAField1Field2LongerField3 
BBField4Field5Field6VeryVeryLongField7Field8 
CCField99 

使用Gawk的我可以設置FIELDWIDTHS,而是適用於整個文件(除非我缺少一條記錄,由記錄的基礎設置這個的一些方法)或者我可以將FS設置爲「」並一次處理文件一個字符,但這有點麻煩。

有沒有一種很好的方法來使用Awk從這樣的文件中提取字段?

編輯:是的,我可能使用Perl(或別的東西)。儘管如此,我仍然渴望知道是否有一種明智的做法。

回答

8

希望這會導致你在正確的方向。假設你的多行記錄保證被'CC'類型的行終止,你可以使用簡單的if-then邏輯預處理你的文本文件。我推測你需要在一行上有1,5和7字段,並且會有一個樣例awk腳本。

BEGIN { 
     field1="" 
     field5="" 
     field7="" 
} 
{ 
    record_type = substr($0,1,2) 
    if (record_type == "AA") 
    { 
     field1=substr($0,3,6) 
    } 
    else if (record_type == "BB") 
    { 
     field5=substr($0,9,6) 
     field7=substr($0,21,18) 
    } 
    else if (record_type == "CC") 
    { 
     print field1"|"field5"|"field7 
    } 
} 

創建一個名爲program.awk的awk腳本文件並將該代碼彈出。執行腳本使用:

awk -f program.awk < my_multi_line_file.txt 
+2

您可以使用與Jonathan Leffler的答案類似的匹配。然後做你的子串提取。 – 2009-09-08 13:53:09

0

更好地使用一些功能完備的腳本語言,如Perl或紅寶石。

3

你可以使用Perl,然後選擇一個基於該行的前兩個字符的解壓縮模板?

+0

是的,謝謝。我在十年內沒有碰過Perl,但是如果我沒有找到用Awk實現這一點的明智方式,我可以按照你的建議。 – 2009-09-08 12:00:15

0

2腳本怎麼樣?例如。第一個腳本根據第一個字符插入字段分隔符,那麼第二個腳本應該處理它?

或者首先在你的AWK腳本中定義一些函數,它根據輸入將行分解爲變量 - 我會這樣做,以便可能的重用。

4

您可能需要抑制(或至少忽略)awk的內建場分離代碼,和沿行使用的程序:

awk '/^AA/ { manually process record AA out of $0 } 
    /^BB/ { manually process record BB out of $0 } 
    /^CC/ { manually process record CC out of $0 }' file ... 

手動處理會有點繁瑣 - 我想你需要使用substr函數來提取每個字段的位置,所以我得到的每條記錄類型只有一行,更像是每個記錄類型的每行一行,以及後續打印。

我的確認爲,使用Perl和它的unpack功能可能會更好,但awk也可以處理它,儘管很複雜。

+0

我不認爲「'$ 0〜'」是必要的 - '/^AA /'部分本身完全匹配。 – 2009-09-08 13:51:43

+0

你是對的;我寫的沒有錯,但也不是最小的。 – 2009-09-08 14:11:32

5

您也許可以使用兩遍:

1step.awk

/^AA/{printf "2 6 6 12" } 
/^BB/{printf "2 6 6 6 18 6"} 
/^CC/{printf "2 8"   } 
{printf "\n%s\n", $0} 

2step.awk

NR%2 == 1 {FIELDWIDTHS=$0} 
NR%2 == 0 {print $2} 

然後

awk -f 1step.awk sample | awk -f 2step.awk 
相關問題