3

次のような入力ファイルがあります。

MB1 00134141 
MB1 12415085 
MB1 13253590
MB1 10598105
MB1 01141484
...
...
MB1 10598105

5行を結合して1行にまとめたい。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

pastemapfileはるかに優れていますが、以前のベースのソリューションを削除することはできませんでした。

[更新:バージョン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

入力を読み取らなくてもステータス0で存在するwhile mapfile ...; doため、実行できません。mapfile

于 2012-08-22T14:50:47.143 に答える
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 に答える
3

sed を使用しますが、これは係数 5 に追加されない最後の数行を処理しません。

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

コマンドは次のN行を読み取り、改行を保持して現在の行に追加します。このスクリプトは、読み取る行ごとに 4 つの追加行を読み取り、バッファーに 5 行のチャンクを蓄積します。そのようなチャンクごとに、すべての改行をスペースに置き換えます。

于 2012-08-22T14:26:58.687 に答える
3

xargs入力に常に一定数のスペースが含まれている場合は、を使用できます。

cat timing_deleted.csv | xargs -n 10

これは、10 個の ( ) 空白文字から入力を受け取り、入力cat timing_deleted.csvを結合します。-n 10などの各列のスペースはMB1 00134141、空白文字としてカウントされます。また、各行の最後の改行も同様です。したがって、5 行の場合は 10 を使用する必要があります。

EDIT
チャールズがコメントしたように、使用をスキップしcatてデータを直接プッシュできますxargs

xargs -n 10 < timing_deleted.csv

非常に大きなファイルを使用してもパフォーマンスの向上は見られませんでしたが、複数のコマンドは必要ありません。

于 2012-08-22T14:27:54.553 に答える
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 に答える