相反的sed
,你總是可以在每個字符域模式下使用awk
(FS=""
):
awk 'BEGIN {
RS = "\n" ;
FS = "" ;
d = 0 ;
}
{
for (i=1; i<=NF; i++)
if ($i == "{") {
d++ ;
if (d == 1) printf "{\n"
} else
if ($i == "}") {
d-- ;
if (d == 0) printf "}"
} else
if (d == 0)
printf "%s", $i ;
if (d == 0) printf "\n"
}' INPUT-FILE(s)...
以上將跳過任何一對大括號,即內容函數和結構體,數組初始化等,並將結果輸出到標準輸出。您可以指定一個或多個文件。 (如果你沒有指定任何文件,它會預期來自標準輸入的輸入。)
現在,它會在引號或註釋中對大括號感到困惑。這可以用相同的方式解決,但它確實變得非常複雜。這只是一個讓你大部分路線的黑客。
我添加了分號(;
),以便您可以將所有內容填入上面的代碼片段中。
腳本的邏輯非常簡單。它使用空字段分隔符(FS
),以便輸入中的每個字符都是它們自己的字段。在處理任何輸入之前,BEGIN
規則將運行一次,並對其進行設置。對於開發者信息,我也初始化d = 0
,雖然它不需要awk,因爲它假定未初始化的變量爲空或零。它將跟蹤每個輸入字符的當前支架深度。
第二個支撐表達式將對每個記錄執行一次。由於我設置了RS = "\n"
,每行都是一個單獨的表達式。因此,它將在每個輸入行中執行一次。由於FS = ""
,該行上的每個字符將是一個單獨的字段。該記錄中有NF
字段:$1
,$2
,..,$(NF-1)
和$NF
。三部分if子句只是輸出最外面的大括號,而不是大括號內的所有內容(即當d == 0
)。
有可能延長這一awk
小腳本以包括註釋,字符串,字符常量(用\047
指一個單引號,除非你把腳本與#!/usr/bin/awk -f
一個單獨的文件),並處理或忽略預處理宏。
它確實有點複雜,你最終會得到幾百行awk腳本,但它應該是相當可靠和相當快的。這是可能的原因是因爲在這個特定情況下C中的標記化規則很容易遵循;我個人會在所有其他用例中使用全面的C詞法分析器(詞法分析器或掃描儀)。也可能是爲了這個。
如果你想使用一個成熟的C詞法分析器,網絡上有一些可以自由使用的語言,但你必須使用更高級的語言,比如C或C++。如果你想處理所有的角落案例,它也需要加入一個C/C++預處理器,但這些規則很容易(即使使用awk)。
你應該解釋你爲什麼這麼問。 –