3

我有一个输入文件如下:

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
4

6 回答 6

8

使用 tr:

cat input_file | tr "\n" " "
于 2014-07-15T17:52:28.373 回答
5

使用粘贴命令:

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

paste好得多,但我不能让自己删除我以前mapfile的基于解决方案。

[更新:与4.2.35版本一起使用时mapfile读取了太多行]-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,因为mapfile即使它没有读取任何输入,它也以状态 0 存在。

于 2012-08-22T14:50:47.143 回答
3

使用 sed,但这个不会处理最后几行不加到 5 的因素:

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

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

于 2012-08-22T14:26:58.687 回答
3

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

cat timing_deleted.csv | xargs -n 10

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

编辑
正如查尔斯评论的那样,您可以跳过使用cat并直接将数据推送到xargs

xargs -n 10 < timing_deleted.csv

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

于 2012-08-22T14:27:54.553 回答
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 的倍数的文件。

于 2012-08-22T14:44:07.200 回答
1

一个 awk 脚本可以做到这一点。我猜也是一个 sed 替换。我不太了解 sed,所以给你。

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

也应该相当快。

于 2012-08-22T16:32:10.577 回答