2014-09-27 18 views
0

我正在編寫一個報告工具,它處理某些應用程序的源文件,並生成一個包含兩列的報告表,一列包含文件的名稱,另一列包含單詞TODO如果該文件包含對某些棄用函數deprecated_functionDONE的調用,則以其他方式。如何重寫一個Awk腳本來處理多個文件而不是一個

我用awk編寫本報告和我的shell腳本看起來像

report() 
{ 
    find . -type f -name '*.c' \ 
    | xargs -n 1 awk -v deprecated="$1" ' 
BEGIN { status = "DONE" } 
$0 ~ deprecated{ status = "TODO" } 
END { 
    printf("%s|%s\n", FILENAME, status) 
}' 
} 
report "deprecated_function" 

這個腳本的輸出看起來像

./plop-plop.c|DONE 
./fizz-boum.c|TODO 

這種運作良好,但我想重寫awk腳本以便它支持多個輸入文件而不僅僅是一個 - 這樣我就可以將-n 1參數移除到xargs。我能找到的唯一解決方案涉及很多簿記,因爲我們需要跟蹤FILENAMEEND事件的更改,以捕獲文件事件的每個結束。

awk -v deprecated="$1" ' 
BEGIN { status = "DONE" } 
oldfilename && (oldfilename != FILENAME) { 
    printf("%s|%s\n", oldfilename, status); 
    status = DONE; 
    oldfilename = FILENAME; 
} 
$0 ~ deprecated{ status = "TODO" } 
END { 
    printf("%s|%s\n", FILENAME, status) 
}' 

也許有一個更清潔和更短的方式來處理這個問題。

我使用的是FreeBSD的awk,我正在尋找與此工具兼容的解決方案。

回答

3

這將在任何現代AWK工作:

awk -v deprecated="$1" -v OFS='|' ' 
    $0 ~ deprecated{ dep[FILENAME] } 
    END { 
     for (i=1;i<ARGC;i++) 
      print ARGV[i], (ARGV[i] in dep ? "TODO" : "DONE") 
    } 
' file1 file2 ... 

你需要製作的所有文件的報告,並沒有GNU AWK的ENDFILE任何時候,你必須遍歷ARGV []到底部分(或通過在BEGIN中循環併爲END部分處理填充不同的數組)。如果你有空文件,其他任何東西都會失敗。

+1

這*是一個改進!感謝您的見解! – 2014-09-27 15:40:46

+2

+1用於避免重複並確保沒有輸入=不輸出 – 2014-09-27 15:49:46

1

你的awk腳本可能是這樣的:

awk -v deprecated="$1" ' 
FNR==1 {if(file) print file "|" (f?"TODO":"DONE"); file=FILENAME; f=0} 
$0 ~ deprecated {f=1} 
END {print file "|" (f?"TODO":"DONE")}' file1.c file2.C# etc. 

的邏輯非常相似,你的程序,所以希望這一切都清楚了。 FNR是當前文件的記錄編號,我正用它來檢測新文件的開始。無可否認在END區塊有一些重複,但我認爲這不是什麼大問題。如果你願意,你可以隨時使用一個功能。

測試出來:

$ cat f1.c 
int deprecated_function() 
{ 
    // some deprecated stuff 
} 
$ cat f2.c 
int good_function() 
{ 
    // some good stuff 
} 
$ find -name "f?.c" -print0 | xargs -0 awk -v deprecated="deprecated" 'FNR==1 {if(file) print file "|" (f?"TODO":"DONE"); file=FILENAME; f=0} $0 ~ deprecated {f=1} END {print file "|" (f?"TODO":"DONE")}' 
./f2.c|DONE 
./f1.c|TODO 

我已經使用-print0-0開關xargs的,這樣由空字節「\ 0」,而不是空格分隔工作的文件名這兩個程序。這意味着你不會遇到文件名中空格的問題。

+0

這與我自己的解決方案非常相似,因爲它需要跟蹤「FILENAME」變化並監視「END」......所以似乎沒有真正的方法來避免這種情況。對於'-0',我們始終將我們的人員使用源文件名中的空格發送給動物標本部門,但這種說法可能對臨時讀者有用。 – 2014-09-27 11:08:17

+1

我不認爲有任何方法可以避免使用您的awk版本。如果您使用的是GNU awk,我會建議使用'ENDFILE' ...我剛剛編輯它以縮小長度。我相信還有更多可以完成的事情,但也許會以可讀性爲代價。 – 2014-09-27 11:24:09

+1

請注意'deprecated'是一個變量,因此您不能在正則表達式中使用它。 – 2014-09-27 15:38:26

相關問題