2013-01-18 17 views
1

我有一個相當大的csv文件,其中每行應以管道(|)結尾,並且如果它沒有將下一行組合到它中,直到再次找到管道。這需要使用shell腳本完成。如果沒有以管道結尾,合併csv行

我得到的回答是

awk '!/|$/{l=l""$0|next|}{print l""$0|l=""}' file 

但它給我的錯誤是每一行的大小對我來說是相當大的。我發現我應該使用Perl來做到這一點,並嘗試了下面的東西,但它確實產生了期望的結果。

perl -pe 's/^\n(|\n)/ /gs' input.csv > output.csv 

我的數據看起來像

A|1|abc|<xml/>| 
|2|def|<xml 
>hello world</xml>| 
|3|ghi|<xml/>| 

和所需的輸出應該

A|1|abc|<xml/>| 
|2|def|<xml>hello world</xml>| 
|3|ghi|<xml/>| 

顯然行大小比這裏的樣品輸入相當大。

任何幫助將不勝感激。

回答

0

這應該工作:

perl -lne 'unless(/\|$/){$line=$line.$_}else{print $line." $_";undef $line}' your_file 

,如果你想要做的就地更換做到這一點:

perl -i -lne 'unless(/\|$/){$line=$line.$_}else{print $line." $_";undef $line}' your_file 

檢查here關於您的評論

+0

對不起,我現在已經糾正它。它是我正在尋找的管道。剛剛嘗試你的解決方案。 – Junaid

+0

儘管如此,如果所有行都以管道(|)結尾,那麼您的解決方案仍然是個小問題,如果腳本不需要任何更改,那麼腳本不會輸出任何要打印行的內容。 – Junaid

+0

你是wrong.its工作,即使所有的行都以pipe.check結束:http://ideone.com/YmHlud – Vijay

0

這應該高高興興地處理所有的情況下爲你,並且在任何行長度上不中斷:

#!/bin/bash 
newLine=0 
IFS= 
while read -r -n 1 char; do 
    if [[ $char =~ ^$ ]]; then 
     if [[ $newLine -eq 1 ]]; then 
      newLine=0 
      echo '|' # add a newline 
     fi 
    elif [[ $char =~ . && ($newLine -eq 1) ]]; then 
     newLine=0 
     echo -n "|$char" 
    elif [[ $char =~ [|] ]]; then 
     if [[ $newLine -eq 1 ]]; then 
      echo -n '|' 
     fi 
     newLine=1 
    else 
     echo -n $char 
    fi 
done < file.txt 

請注意,在bash中手動構建一個詞法分析器通常是一個糟糕的主意。

1
awk '{printf "%s",$0} /[|][[:space:]]*$/ {print ""}' 

打印沒有換行符的每一行。如果最後一個非空白字符是一個管道,那麼你需要一個完整的行來打印一個換行符。

+0

awk給出了記錄大小的錯誤,我相信它不能處理大的行。 – Junaid

+0

線條有多大?數以百萬計的人物? –

+0

是的,它可以很容易地達到一百萬,因爲我用作輸入的csv文件是從具有HUGECLOB作爲數據類型的表導出數據庫的結果。無論如何感謝您的幫助。 – Junaid