击:结合输入的五线输出的每一行(bash: combine five lines of input

2019-09-21 11:20发布

我有一个输入文件,如下所示:

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

Answer 1:

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



Answer 2:

使用TR:

cat input_file | tr "\n" " "


Answer 3:

使用粘贴命令:

 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的存在,即使它不读任何输入。



Answer 4:

您可以使用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

我没有注意到使用一个真正的大文件的任何性能提升,但它并不需要多条命令。



Answer 5:

使用SED,但是这一次将不会处理最后几行不增加5倍:

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

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



Answer 6:

一个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

应该是相当快。



文章来源: bash: combine five lines of input to each line of output
标签: bash shell unix