我有一个输入文件,如下所示:
MB1 00134141
MB1 12415085
MB1 13253590
MB1 10598105
MB1 01141484
...
...
MB1 10598105
我想结合5行并将其合并成一行。 我希望我的bash脚本来处理bash脚本生成的输出如下 -
MB1 00134141 MB1 12415085 MB1 13253590 MB1 10598105 MB1 01141484
...
...
...
我已经写了下面的脚本和它的作品,但它是规模23051行的文件慢。 我可以写出更好的代码,使其更快?
#!/bin/bash
file=timing.csv
x=0
while [ $x -lt $(cat $file | wc -l) ]
do
line=`head -n $x $file | tail -n 1`
echo -n $line " "
let "remainder = $x % 5"
if [ "$remainder" -eq 0 ]
then
echo ""
fi
let x=x+1
done
exit 0
我试图执行下面的命令,但它搅乱了一些数字。
cat timing_deleted.csv | pr -at5
在纯bash中,没有外部的过程(速度):
while true; do
out=()
for (( i=0; i<5; i++ )); do
read && out+=( "$REPLY" )
done
if (( ${#out[@]} > 0 )); then
printf '%s ' "${out[@]}"
echo
fi
if (( ${#out[@]} < 5 )); then break; fi
done <input-file >output-file
这正确地处理文件,其中的行数不是5的倍数。
使用TR:
cat input_file | tr "\n" " "
使用粘贴命令:
paste -d ' ' - - - - - < tmp.txt
paste
好远,但我不能让自己删除我以前的mapfile
为基础的解决方案。
[UPDATE: mapfile
读取之前版本太多行4.2.35当用于-n
]
#!/bin/bash
file=timing.csv
while true; do
mapfile -t -n 5 arr
(( ${#arr} > 0 )) || break
echo "${arr[*]}"
done < "$file"
exit 0
我们不能做while mapfile ...; do
while mapfile ...; do
是因为mapfile
状态为0的存在,即使它不读任何输入。
您可以使用xargs
,如果你的输入总是包含的每行空间一致的数字:
cat timing_deleted.csv | xargs -n 10
这将需要从输入cat timing_deleted.csv
和10(组合输入-n 10
)空格字符。 每一列中的空间,如MB1 00134141
,算作一个空白字符-以及在每一行的末尾的换行符。 因此,对于5号线,你需要使用10。
编辑
作为评论的查尔斯,你可以跳过的使用cat
,并直接将数据推入xargs
有:
xargs -n 10 < timing_deleted.csv
我没有注意到使用一个真正的大文件的任何性能提升,但它并不需要多条命令。
使用SED,但是这一次将不会处理最后几行不增加5倍:
sed 'N;N;N;N;s/\n/ /g;' input_file
的N
命令读取下一行并将其附加到当前行,并保留换行符。 此脚本读取用于在每次读取,积累的5条线在缓冲块线四个额外的线。 对于每一次这样的块,它取代所有用空格换行符。
一个awk脚本会做到这一点。 一个sed更换过,我猜。 我不知道SED好,所以在这里你去。
NF{
if(i>=5){
line = line "\n";
i=0;
}else{
line = line " " $0;
i++;
}
}
END{
print line;
}
呼叫,说,merge.awk。 这里是你如何invoque它:
awk -f merge.awk filetomerge.txt
或cat filetomerge.txt | awk -f merge.awk
cat filetomerge.txt | awk -f merge.awk
应该是相当快。