2016-05-14 99 views
0

我正在使用sqlldr腳本將數據加載到Oracle表中。它生成3個文件,一個日誌文件,壞數據文件和丟棄的記錄文件。awk腳本來檢查文件是否存在併合並文件中的行

我在網絡上發現了一個漂亮的腳本,它解析這些文件並將日誌文件中的錯誤與適當的記錄關聯起來。我不記得我找到的網站。我現在想在腳本中添加一個檢查來檢查這些文件是否存在,並且我正在嘗試理解腳本,以便添加邏輯。

我還沒有做awk之前。

這是腳本。請有人解釋前4行是什麼?

awk ' 
FNR==1 { FileNum++ } 
FileNum==1 { Bad[FNR] = $0 ; next } 
FileNum==2 { Dis[FNR] = $0 ; next } 
/^Record [0-9]+: Rejected/ { 
    rec = Bad[++Rejected]; 
    col = $NF; 
    getline; 
    sub(/^ORA-[^:]*:[[:space:]]*/, ""); 
    print rec, "Error on column", col; 
    next; 
} 
/^Record [0-9]+: Discarded/ { 
    rec = Dis[++discarded]; 
    sub(/.*Discarded - /, "") 
    print rec, $0; 
    next; 
} 
' file.bad file.discarded file.log 

UPDATE ======

@Ed - 例如低於

添加文件的例子和預期輸出

SQLLDR完成執行後,三個文件已被克隆, - 日誌文件 - 錯誤的數據文件,並 - 丟棄記錄文件

日誌文件將具有控制文件,然後任何錯誤都記錄

例如

Record 5: Discarded - failed all WHEN clauses。 - 這一切都被丟棄的文件

- 以下2轉到壞數據文件

Record 6: Rejected - Error on table SCH_USER.TEMP_RESULT. 
ORA-00001: unique constraint (SCH_USER.PK_TEMP_RESULT) violated 

Record 7: Rejected - Error on table SCH_USER.TEMP_RESULT. 
ORA-00001: unique constraint (SCH_USER.PK_TEMP_RESULT) violated 

**Log file** 
Record 5: Discarded - failed all WHEN clauses 

Record 6: Rejected - Error on table SCH_USER.TEMP_RESULT. 
ORA-00001: unique constraint (SCH_USER.PK_TEMP_RESULT) violated 

Record 7: Rejected - Error on table SCH_USER.TEMP_RESULT. 
ORA-00001: unique constraint (SCH_USER.PK_TEMP_RESULT) violated 

**Discarded file** 
6296|0205|351004|666181|F.8.5|C|1|3|GP| 

**Bad data file** 
6296|0205|441201|666181|F.8.5|E|1|3|CS| 
6296|0205|461210|666181|F.8.5|E|1|3|EM GW| 

運行該腳本後,將輸出重定向到一個文件時,輸出看起來像這樣

6296|0205|351004|666181|F.8.5|C|1|3|GP| failed all WHEN clauses. 
6296|0205|441201|666181|F.8.5|E|1|3|CS| ******************Error on table SCH_USER.TEMP_RESULT. Actual Error : ORA-00001: unique constraint (SCH_USER.PK_TEMP_RESULT) violated 
6296|0205|461210|666181|F.8.5|E|1|3|EM GW| ******************Error on table SCH_USER.TEMP_RESULT. Actual Error : ORA-00001: unique constraint (SCH_USER.PK_TEMP_RESULT) violated 

在上面的場景中,有可能是壞數據文件或丟棄文件或兩者都不存在(這是個好消息,使用sqlldr時沒有錯誤)。我希望能夠使用腳本優雅地處理這兩個場景。

我希望這是可能的。你會讓我知道嗎,我該如何實現它?

回答

1

FNR==1 { FileNum++ } FNR是文件記錄號,它的每個文件後重置,使用這種條件腳本知道是什麼文件,它的工作對

FileNum==1 { Bad[FNR] = $0 ; next }如果腳本處理的第一個文件中的線($ 0)添加到使用記錄號索引的數組(這裏是行),next跳過腳本的其餘部分以處理下一條記錄。

FileNum==2 {相同現在第二文件

/^Record [0-9]+: Rejected/現在腳本處理所述第三文件,模式匹配每行開始「記錄」,空間,一個或多個數字,「:被拒絕」。對於匹配的行,請執行塊中的操作。

UPDATE awk通過記錄操作文件記錄(此處默認記錄是行)。使用這種方法它只會查找非空文件,空文件將被跳過。在新文件中,文件記錄號FNR將重置爲1.檢查此值將指示是否完成一個文件並啓動下一個(非空)文件。 FileNum是用戶定義的變量。該腳本是在考慮輸入參數的情況下編寫的。前兩個文件將存儲在由行號索引的數組中,並在第三個文件上作爲參考進行操作。它不知道文件是否存在,如果文件不存在就會失敗。在調用awk之前將其保留爲shell可能會更好。

+0

謝謝。仍試圖瞭解第一行的功能。那麼,它是否通過比較我們是否在第一條記錄來檢查它是否是新文件,如果我們是那麼它會增加FileNum變量?它如何確定文件的總數量。它是否發生在隱式循環中? FileNum也是一個awk特定變量,還是用戶定義的?所以,如果我想檢查文件是否存在,那麼在檢查FileNum == 1或2之後,我應該在大括號內進行檢查嗎?對於大量問題抱歉,但在網上搜索時找不到這種類型的詳細信息。 – adbdkb

+0

@adbdkb所有這些細節和更多內容都在Arnold Robbins出版的第4版Effective Awk Programming中進行了解釋。 –

+0

再次感謝@karakfa - 我已經對它如何執行程序有了很高的理解,並且您的解釋將幫助我破譯代碼。我想檢查腳本中是否存在文件的原因是,在sqlldr按計劃運行後,我將每天使用它。因此,有時候壞的和dsc文件中的一個或兩個文件不存在,所以我想檢查並執行適當的處​​理。那是可行的嗎?和一個有效的想法?或者你還是建議在調用awk之前在外面做這件事?這不需要我有多個awk腳本? – adbdkb

0

貌似OP可能已經離開大樓,但對其他任何人想知道如何明確處理不存在或無法打開其他原因的文件,這裏的做法:

$ cat ../tst.awk 
BEGIN { 
    badFiles = rmvBadFiles() 
    if (badFiles != "") { 
     printf "ERROR: cannot read from file(s):\n%s\n", badFiles | "cat>&2" 
     # Add "exit 1" if you want to exit instead of continuing 
    } 
} 
{ print FILENAME, $0 } 

function rmvBadFiles( _argind,_file,_line,_badFiles) { 
    for (_argind=1; _argind < ARGC ; _argind++) { 
     _file = ARGV[_argind] 
     if (_file !~ /^([[:alnum:]_]+=.*|-?)$/) { 
      if ((getline _line < _file) < 0) { 
       _badFiles = (_badFiles == "" ? "" : _badFiles "\n") _file 
       ARGV[_argind] = "" 
      } 
      close(_file) 
     } 
    } 
    return _badFiles 
} 

例如:

$ ls 
file1 file2 
$ cat file1 
a 
$ cat file2 
b 
$ awk -f ../tst.awk file1 garbage file2 
file1 a 
file2 b 
ERROR: cannot read from file(s): 
garbage 

,而不是默認的行爲:

$ awk '{print FILENAME, $0}' file1 garbage file2 
file1 a 
awk: cmd. line:1: fatal: cannot open file `garbage' for reading (No such file or directory) 
+0

不,沒有離開大樓:) - 只是試圖創建可以使用的小測試數據 - 將能夠今天上載它 – adbdkb

+0

你的解釋和例子也有很多幫助,但卡拉夫卡最初解釋了我最初的問題已經問過了,所以接受了這個答案 – adbdkb

相關問題