2013-01-10 31 views
4

我對UNIX編碼相當新穎,我有一個文件,我需要逐行反向讀取。該文件在{}中包含代碼部分。然後我需要用這個反轉文件作爲輸入運行一個awk腳本。我有我們的支持人員安裝tac,但在他們之前,我想知道它是否會輸出我需要的或者是否有人可以建議替代方案。使用tac讀取反向文件

該文件在表單數據:

page 0 0 0 none 
{ 
    layer 0 0 0 "1line" 0 8 8 3 
    { 
     sector 0 -1 0 32 
     { 
     point_name 0 0 34543 34 44 1 1 0 
     status 1 0 1 0 1 431232 "transformer" 23 12 
     analog 1 0 1 0 1 321234 11.5 43 1 1 0 
     ... 
     ... 
     ... 
     device 1 0 1 "ground" 32 56 1 1 0 
     } 
    } 
} 

,我想保留{}但反向的線{}所以出來放樣子:

page 0 0 0 none 
{ 
    layer 0 0 0 "1line" 0 8 8 3 
    { 
     sector 0 -1 0 32 
     { 
     device 1 0 1 "ground" 32 56 1 1 0 
     ... 
     ... 
     ... 
     analog 1 0 1 0 1 321234 11.5 43 1 1 0 
     status 1 0 1 0 1 431232 "transformer" 23 12 
     point_name 0 0 34543 34 44 1 1 0 
     } 
    } 
} 

而且,tac覆蓋輸入文件還是將其另存爲另一個文件?

回答

1

最喜歡的Unix (風格)工具tac既不覆蓋一部開拓創新的文件或寫一個新的,它打印到stdout,寫有tac一個新的文件中,可以使用重定向tac file > newfile這將節省逆轉filenewfile 。您無法單獨使用tac來滿足您的要求,您需要一個腳本。

這是一個在awk

{ 
    # store each line in the array line 
    line[n++] = $0 
} 

/{/ { 
    # get the line number of the last line containing { 
    first=NR 
} 

!/}/ { 
    # get the line number of the last line not containing } 
    last=NR 
} 

END { 
    # print first section in order 
    for (i=0;i<first;i++) 
     print line[i] 
    # print second section in reverse order 
    for (i=last-1;i>=first;i--)  
     print line[i] 
    # print last section in order 
    for (i=last;i<NR;i++) 
     print line[i] 
} 

保存這一個文件說reverse然後運行awk -f reverse file

$ awk -f reverse file 
page 0 0 0 none 
{ 
    layer 0 0 0 "1line" 0 8 8 3 
    { 
     sector 0 -1 0 32 
     { 
     device 1 0 1 "ground" 32 56 1 1 0 
     ... 
     ... 
     ... 
     analog 1 0 1 0 1 321234 11.5 43 1 1 0 
     status 1 0 1 0 1 431232 "transformer" 23 12 
     point_name 0 0 34543 34 44 1 1 0 
     } 
    } 
} 

使用重定向將創建一個新的文件awk -f reverse file > newfile

+0

沒有做一些修改,這將失敗比給出的精確輸入以外的任何 - 這可能不是OP想要什麼。我會幫你解決這個問題,但這不是你想解決這個問題的方法。另外,現在是凌晨2點半,我要睡覺......晚上。 – Steve

+0

@steve的方式,我明白了問題的代碼是很好格式從未'}''之前到來{'所以我一直腳本簡單,易於理解。 –

1

tac只是顛倒了文件的行順序,因此您需要更強大的功能來完成您想要的功能。而且,所有shell工具都不包含覆蓋輸入文件的方式,而不使用「temp」文件。一些工具(例如sed,Perl等)具有所謂的「就地編輯」選項,即當沒有提供備份文件後綴時,將會給出文件覆蓋的最終結果。

要完成你想要的任務,我建議使用awk。運行像:

awk -f script.awk file > newfile 

要覆蓋輸入文件,使用臨時文件,運行:

awk -f script.awk file > temp && mv temp file 

內容的script.awk

/{/ { 
    print (a ? a ORS : "") $0 
    f=1; a=b="" 
    next 
} 

f && !/}/ { 
    a = (a ? a ORS : "") $0 
    b = $0 (b ? ORS b : "") 
    next 
} 

/}/ && b { 
    print b ORS $0 
    a=b=f="" 
    next 
}1 

結果:

page 0 0 0 none 
{ 
    layer 0 0 0 "1line" 0 8 8 3 
    { 
     sector 0 -1 0 32 
     { 
     device 1 0 1 "ground" 32 56 1 1 0 
     ... 
     ... 
     ... 
     analog 1 0 1 0 1 321234 11.5 43 1 1 0 
     status 1 0 1 0 1 431232 "transformer" 23 12 
     point_name 0 0 34543 34 44 1 1 0 
     } 
    } 
} 

可替代地,這裏的一個襯裏:

awk '/{/ { print (a ? a ORS : "") $0; f=1; a=b=""; next } f && !/}/ { a = (a ? a ORS : "") $0; b = $0 (b ? ORS b : ""); next } /}/ && b { print b ORS $0; a=b=f=""; next }1' file 

說明:

的第一碼塊詢問是否行包含一個開口支架。如果是這樣,打印記錄中的任何內容「a」,後面跟着當前記錄(包含大括號的行)。設置一個標誌,刪除記錄'a'和'b'並跳過處理其餘的代碼。

當且僅當該標誌已被設置的第二個塊將被執行,並且行不包含一閉括號。現在我們建立兩個記錄'a'和'b'。回想一下,如果一條線包含大括號,則打印記錄「a」。所以它必須建立在'開始到結束'的方向上。然後我們在'結束開始'的方向建立記錄'b'。 '下一步'然後跳過處理其餘的代碼。如果該行包含一個右括號和記錄「B」(記住,這是在相反方向的記錄版本)

第三塊將被執行。然後我們打印記錄'b',然後打印當前行(帶大括號的行)。刪除記錄'a','b'並重置標誌。 '接下來'跳過處理其餘的代碼。最後的'1'啓用默認打印。

+0

好的回答';)介紹腳本的思想? –

+0

@sudo_O:我添加了一個解釋。說實話,代碼比解釋更有意義(至少對我來說)。 HTH。 – Steve

+0

謝謝兩位的快速響應,我會稍後再試他們兩人,並讓你知道,如果他們解決我的問題 – user1966709