我有一个相当大的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/>|
显然,线条尺寸比这里输入的样本要大。
任何帮助都将受到高度赞赏。
答案 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中手动构建词法分析器通常是一个坏主意。