2012-08-25 46 views
1

我被困在看起來應該對SED來說很簡單的東西中。SED - 通過文件的其餘部分刪除第一行的出現

我有一些(類)的CSV文件,我從另一個應用程序中獲得,所以我無法控制它的輸出。一些預處理已經完成了SED,但是我被困在最後一個。因此,如果可能的話,我希望用SED來做,以避免使用第三個應用程序。

的問題是,該文件(第一行)的標題線沿文件重複,但遺憾的是具有以下特徵:

  1. 每個CSV文件的標題是未知的先前。每個文件都有自己的標題,可能彼此不同;發生在每N行(爲N固定的已知數量)
  2. 其他數據(非標題)線可能被重複
  3. 不總是重複,並應保持

因此,假設我有以下2檔:

Cash.csv

Name; Amount 
John; 3.55 
Erick; 4.76 
John; 8.99 
Name; Amount 
Erick; 4.76 
Mark; 1.00 
Name; Amount 
John; 3.55 

Check.csv

Name; Account; Amount 
Erick; 345344; 123.00 
Mark; 88849; 323.50 
Name; Account; Amount 
John; 474473; 99.00 
Mark; 88849; 323.50 
Mark; 88849; 323.50 
John; 474473; 99.00 

我希望的是,應用到每一個文件一個sed腳本把它們變成:

Cash.processed.csv

Name; Amount 
John; 3.55 
Erick; 4.76 
John; 8.99 
Erick; 4.76 
Mark; 1.00 
John; 3.55 

Check.processed.csv

Name; Account; Amount 
Erick; 345344; 123.00 
Mark; 88849; 323.50 
John; 474473; 99.00 
Mark; 88849; 323.50 
Mark; 88849; 323.50 
John; 474473; 99.00 

我想知道是否可以使用SED「保留緩衝區」作爲刪除命令的模式:

1h  #Hold the first line (headings) 
/\h/d #Use hold buffer as a pattern to delete 

假設「\ h」會將保留緩衝區返回給刪除命令。

感謝您的回覆;

PS:請不要使用以下過特定命令回答:

1p;/Name; Amount\|Name; Account; Amout/d 
+0

喬納森,謝謝你的提示。沒有足夠的聲望,但只要我得到它,我會標記爲有用。我很長一段時間只讀堆棧溢出風扇。我沒想到會得到有用的答案,所以現在我是一個很大的SO粉絲。謝謝你們! – RFVoltolini

回答

4

我想你會需要從一個sed命令捕獲的第一行,然後使用主作戰指揮:看完第一行之後

line1=$(sed 1q $datafile) 

sed -e "2,$ {/$line1/d;}" \ 
    -e '...rest of sed script...' $datafile 

因爲sed 1q提出辭聘的,不管數據文件有多大快。如果有一個機會,第一行可能包含一個斜槓(標題"Name/Number",也許)或其它正則表達式元字符,然後想用這樣的事情,它取代所有的斜線與.的:

line1=$(sed '1{s%/%.%g;q;}' $datafile) 

我做了一些把玩與Mac OS X(10.8.1)版本sed,它比GNU sed更加麻煩。在第二個(主要)sed命令中,匹配必須在{...}之間,美元必須是分開的(或者shell對無效的參數替換產生厭倦),並且需要分號。 GNU sed可能不需要這些限制中的一部分,但所顯示的代碼可能在任何地方都有效。

+0

+1我也是這麼做的。如果第一行可能包含正則表達式元字符,它們將需要轉義。 – tripleee

+0

工程就像一個魅力,也很快。一百萬行文件(20MB)耗費了大約0.5秒的時間。 – RFVoltolini

2

這可能爲你工作(GNU SED):

sed '1h;1!{G;/^\(.*\)\n\1/d;s/\n.*//}' file 

說明:

  • 1h店在保持空間(HS)和打印標題行。
  • 1!{G;/^\(.*\)\n\1/d;s/\n.*//}對於除第一行之外的每一行,追加一個換行符,然後是HS的內容(即標題行)。將該行的第一部分與標題行進行比較,如果它是相同的,則刪除該行。如果它沒有刪除附加的換行符和標題行並且照常打印。

編輯:

這確實是對大文件非常慢,更快,也許更容易理解的解決方案是:

sed 's|.*|1!{/^&$/d}|;q' file | sed -f - file 

這使得sed腳本從輸入的第一行文件。

+0

謝謝potong。對於小文件,我猜這1行sed是最好的選擇。但對於更大的文件,這可能會變得非常慢。一個100萬行文件花了我10秒(20MB),而喬納森替代方案花了0.5秒(請參閱接受的答案)。 – RFVoltolini

+0

@RFVoltolini:您的結果時間很有趣。 Potong的sed表達式必須複製每一行,擴展它,使用一個適度複雜的正則表達式(正則表達式中的'\ 1'使其變得複雜,至少在執行它時花費的時間),然後通常將擴展移除這條線,所以它比一個簡單的正則表達式匹配慢並不令人驚訝。不過,我有點驚訝,它慢了20倍。不過,這是一個聰明的表達。 –

+0

@RFVoltolini請參閱編輯。 – potong

1

在情況下,如果你有興趣在AWK:

​​
+0

或更簡單地說:'NR == 1 {p = $ 0}; NR == 1 || p!= $ 0'。 – Thor

+0

或更簡單地說'NR == 1 &&p=$0; p!= $ 0' – potong

+0

哇!小巧,快速,強大!我想我需要花一些時間來學習awk並重寫我的洞腳本。 – RFVoltolini

相關問題