bash:将五行输入组合到每行输出

时间:2012-08-22 14:23:49

标签: bash shell unix

我有一个输入文件如下:

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

6 个答案:

答案 0 :(得分:8)

使用tr:

cat input_file | tr "\n" " "

答案 1 :(得分:5)

使用粘贴命令:

 paste -d ' ' - - - - - < tmp.txt

paste要好得多,但我无法自拔 删除我之前基于mapfile的解决方案。

[更新:与mapfile一起使用时,-n在版本4.2.35之前读取太多行

#!/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因为mapfile存在状态为0,即使它没有读取任何输入。

答案 2 :(得分:3)

如果您的输入始终包含每行一致的空格数,则可以使用xargs

cat timing_deleted.csv | xargs -n 10

这将从cat timing_deleted.csv获取输入,并将输入组合在10(-n 10)个空白字符上。每列中的空格(例如MB1 00134141)将计为空白字符 - 以及每行末尾的换行符。因此,对于5行,您需要使用10。

修改
正如Charles所评论的那样,您可以跳过cat的使用,并直接将数据推送到xargs,其中包含:

xargs -n 10 < timing_deleted.csv

我没有注意到使用非常大的文件会带来任何性能提升,但它不需要多个命令。

答案 3 :(得分:3)

在纯粹的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的倍数的文件。

答案 4 :(得分:2)

使用sed,但是这个不会处理最后几行没有添加到5的因子:

 sed 'N;N;N;N;s/\n/ /g;' input_file

N命令读取下一行并将其附加到当前行,保留换行符。此脚本为其读取的每一行读取另外四行,在缓冲区中累积5行的块。对于每个这样的块,它用空格替换所有换行符。

答案 5 :(得分:1)

awk脚本会这样做。我猜也是一个替代品。我不太了解,所以你走了。

NF{ 
    if(i>=5){
        line = line "\n";
        i=0;
    }else{
        line = line " " $0;
        i++;
    }
}

END{
    print line;
}

称之为merge.awk。这是你如何调用它:

    awk -f merge.awk filetomerge.txt

或        cat filetomerge.txt | awk -f merge.awk

也应该相当快。