如果没有以管道结尾,则合并csv行

时间:2013-01-18 14:00:18

标签: linux bash shell unix

我有一个相当大的csv文件,其中每一行应以管道(|)结束,如果它没有将下一行组合到其中,直到再次找到管道。这需要使用shell脚本完成。

我得到了答案

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/>|

显然,线条尺寸比这里输入的样本要大。

任何帮助都将受到高度赞赏。

3 个答案:

答案 0 :(得分:1)

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

不使用换行符打印每一行。如果最后一个非空白字符是管道,则表示您有一个完整的行,因此请打印换行符。

答案 1 :(得分: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有关您的评论

答案 2 :(得分: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中手动构建词法分析器通常是一个坏主意。