OpenSimStats.txtという名前の次のファイルがあります。
TestreportsRootAgentCount=0agent(s)
TestreportsChildAgentCount=0childagent(s)
TestreportsGCReportedMemory=10MB(Global)
TestreportsTotalObjectsCount=0Object(s)
TestreportsTotalPhysicsFrameTime=0ms
TestreportsPhysicsUpdateFrameTime=0ms
TestreportsPrivateWorkingSetMemory=2144MB(Global)
TestreportsTotalThreads=0Thread(s)(Global)
TestreportsTotalFrameTime=89ms
TestreportsTotalEventFrameTime=0ms
TestreportsLandFrameTime=0ms
TestreportsLastCompletedFrameAt=25msago
TestreportsTimeDilationMonitor=1
TestreportsSimFPSMonitor=55.3333320617676
TestreportsPhysicsFPSMonitor=55.4766654968262
TestreportsAgentUpdatesPerSecondMonitor=0persecond
TestreportsActiveObjectCountMonitor=0
TestreportsActiveScriptsMonitor=0
TestreportsScriptEventsPerSecondMonitor=0persecond
TestreportsInPacketsPerSecondMonitor=0persecond
TestreportsOutPacketsPerSecondMonitor=0persecond
TestreportsUnackedBytesMonitor=0
TestreportsPendingDownloadsMonitor=0
TestreportsPendingUploadsMonitor=0
TestreportsTotalFrameTimeMonitor=18.18239402771ms
TestreportsNetFrameTimeMonitor=0ms
TestreportsPhysicsFrameTimeMonitor=0.0106373848393559ms
TestreportsSimulationFrameTimeMonitor=0.17440040409565ms
TestreportsAgentFrameTimeMonitor=0ms
TestreportsImagesFrameTimeMonitor=0ms
TestreportsSpareFrameTimeMonitor=18.1818199157715ms
TestreportsLastReportedObjectUpdates=0
TestreportsSlowFrames=1
このファイルを次のCSVファイルに変換したいと思います。
TestreportsRootAgentCount,TestreportsChildAgentCount,...,TestreportsSlowFrames
0,0,10,0,0...,1
私の言葉は:
- 区切り記号の前後のすべての単語を削除します。この場合、区切り文字は「=」です。
- 区切り文字の左側にあるすべての単語をカンマで区切って1行に入力します。
- 最後に新しい行を挿入する
- 次に、区切り文字()の
=
後にあるすべての項目を入力します。数字がコンマで区切られた別の行に数字のみを入力します(数字の後に単位または文字なし)。 - 次に、新しい行を挿入します。
Linuxシェルスクリプトでこれを行う方法についてのアイデア/提案はありますか? sedまたはgawkを使用して?
答え1
OpenSimに触発された9つのパス:
sed
さらに、いくつかのシェル魔法も追加されます。
sed 's/=.*//' OpenSimStats.txt | paste -sd, >out.csv
sed 's/.*=//; s/[^0-9]*$//' OpenSimStats.txt | paste -sd, >>out.csv
sed
、シェル魔法なし:
sed -n 's/=.*//; 1{ h; b; }; $! H; $ { x; s/\n/,/g; p; }' OpenSimStats.txt >out.csv
sed -n 's/.*=//; 1{ s/[0-9]*$//; h; b; }; s/[^0-9]*$//; $! H; $ { x; s/\n/,/g; p; }' OpenSimStats.txt >>out.csv
貝殻の魔法といくつかの助けを借りてsed
:
paste -sd, <(cut -d= -f1 OpenSimStats.txt) <(cut -d= -f2 OpenSimStats.txt | sed 's/[^0-9]*$//')
cut
さらに、いくつかのシェル魔法も追加されます。
cut -d= -f1 OpenSimStats.txt | paste -sd, >out.csv
cut -d= -f2 OpenSimStats.txt | sed 's/[^0-9]*$//' | paste -sd, >>out.csv
GNUの使用datamash
:
sed 's/=/,/; s/[^0-9]*$//' OpenSimStats.txt | datamash -t, transpose
そしてperl
:
perl -lnE 's/\D+$//o;
($a, $b) = split /=/;
push @a, $a; push @b, $b;
END { $, = ","; say @a; say @b }' OpenSimStats.txt
そしてgrep
:
grep -o '^[^=]*' OpenSimStats.txt | paste -sd, >out.csv
egrep -o '[0-9.]+' OpenSimStats.txt | paste -sd, >>out.csv
そしてbash
:
#! /usr/bin/env bash
line1=()
line2=()
while IFS='=' read -r a b; do
line1+=("$a")
[[ $b =~ ^[0-9.]+ ]]
line2+=("$BASH_REMATCH")
done <OpenSimStats.txt
( set "${line1[@]}"; IFS=,; echo "$*" ) >out.csv
( set "${line2[@]}"; IFS=,; echo "$*" ) >>out.csv
そしてawk
:
awk -F= '
NR==1 { a = $1; sub(/[^0-9]+$/, "", $2); b = $2; next }
{ a = a "," $1; sub(/[^0-9]+$/, "", $2); b = b "," $2 }
END { print a; print b }' OpenSimStats.txt
データファンのための10番目の方法、csvtk
:
csvtk replace -d= -f 2 -p '\D+$' -r '' <OpenSimStats.txt | csvtk transpose
11番報酬パスvim
:
:%s/\D*$//
:%s/=/\r/
qaq
:g/^\D/y A | normal dd
:1,$-1 s/\n/,/
"aP
:2,$-2 s/\n/,/
:d 1
:w out.csv
答え2
awk
助けることができる場所は次のとおりです。
awk -F= '{a[NR,1]=$1;a[NR,2]=$2}
END{
for(i=1; i<NR; i++){
printf a[i,1] ","
}
print a[i,1];
for(i=1; i<NR; i++){
printf "%s", a[i,2]+0
}
print a[i,2];
}' file
配列は最初の列のキーと2番目の列の値で埋められますa
。$1
$2
すべての行を読み取ったら、配列のすべての要素を2回繰り返してキーと値を表示します。
答え3
Perlソリューションは次のとおりです。
$ perl -F= -lae '$F[1]=~s/[^0-9]//g; push @h,$F[0]; push @l,$F[1];
END{print join ",",@h; print join ",",@l}' OpenSimStats.txt
TestreportsRootAgentCount,TestreportsChildAgentCount,TestreportsGCReportedMemory,TestreportsTotalObjectsCount,TestreportsTotalPhysicsFrameTime,TestreportsPhysicsUpdateFrameTime,TestreportsPrivateWorkingSetMemory,TestreportsTotalThreads,TestreportsTotalFrameTime,TestreportsTotalEventFrameTime,TestreportsLandFrameTime,TestreportsLastCompletedFrameAt,TestreportsTimeDilationMonitor,TestreportsSimFPSMonitor,TestreportsPhysicsFPSMonitor,TestreportsAgentUpdatesPerSecondMonitor,TestreportsActiveObjectCountMonitor,TestreportsActiveScriptsMonitor,TestreportsScriptEventsPerSecondMonitor,TestreportsInPacketsPerSecondMonitor,TestreportsOutPacketsPerSecondMonitor,TestreportsUnackedBytesMonitor,TestreportsPendingDownloadsMonitor,TestreportsPendingUploadsMonitor,TestreportsTotalFrameTimeMonitor,TestreportsNetFrameTimeMonitor,TestreportsPhysicsFrameTimeMonitor,TestreportsSimulationFrameTimeMonitor,TestreportsAgentFrameTimeMonitor,TestreportsImagesFrameTimeMonitor,TestreportsSpareFrameTimeMonitor,TestreportsLastReportedObjectUpdates,TestreportsSlowFrames
0,0,10,0,0,0,2144,0,89,0,0,25,1,553333320617676,554766654968262,0,0,0,0,0,0,0,0,0,1818239402771,0,00106373848393559,017440040409565,0,0,181818199157715,0,1
この-a
フラグは動作を同様にし、各入力行をperl
(ここでは)でawk
指定されたフィールド区切り文字の配列に分割します。各呼び出しに追加され、各行で実行されるスクリプトです。-F
=
@F
-l
\n
print
-e
$F[1]=~s/[^0-9]//g;
:2番目のフィールドから数字以外の文字をすべて削除します($F[1]
2番目のフィールドと同様に、配列はゼロから計算され始めます)。push @h,$F[0]; push @l,$F[1];
:最初のフィールドを配列に追加し、@h
2番目のフィールド(今では数字以外のフィールドは削除)を配列に追加します@l
。END{}
:入力ファイル全体を処理して一度実行します。print join ",",@h;
:@h
配列を連結して,
印刷します。print join ",",@l
:上記と同じですが@l
。
答え4
私はこの質問にすでに答えられていることを知っています。 (醜い)bashでこれを達成する方法について2セントしか追加しないと思いました。
最終結果
echo -e $(cut -d"=" -f1 OpenSimStats.txt | tr '\n' ',' | sed 's/,$/\\n/')$(sed -r 's/.*=([0-9]*).*/\1,/g' OpenSimStats.txt | tr -d '\n' | sed 's/,$//')
これにより、1行に要求され、結果が生成されます。
TestreportsRootAgentCount,TestreportsChildAgentCount,TestreportsGCReportedMemory,TestreportsTotalObjectsCount,TestreportsTotalPhysicsFrameTime,TestreportsPhysicsUpdateFrameTime,TestreportsPrivateWorkingSetMemory,TestreportsTotalThreads,TestreportsTotalFrameTime,TestreportsTotalEventFrameTime,TestreportsLandFrameTime,TestreportsLastCompletedFrameAt,TestreportsTimeDilationMonitor,TestreportsSimFPSMonitor,TestreportsPhysicsFPSMonitor,TestreportsAgentUpdatesPerSecondMonitor,TestreportsActiveObjectCountMonitor,TestreportsActiveScriptsMonitor,TestreportsScriptEventsPerSecondMonitor,TestreportsInPacketsPerSecondMonitor,TestreportsOutPacketsPerSecondMonitor,TestreportsUnackedBytesMonitor,TestreportsPendingDownloadsMonitor,TestreportsPendingUploadsMonitor,TestreportsTotalFrameTimeMonitor,TestreportsNetFrameTimeMonitor,TestreportsPhysicsFrameTimeMonitor,TestreportsSimulationFrameTimeMonitor,TestreportsAgentFrameTimeMonitor,TestreportsImagesFrameTimeMonitor,TestreportsSpareFrameTimeMonitor,TestreportsLastReportedObjectUpdates,TestreportsSlowFrames
0,0,10,0,0,0,2144,0,89,0,0,25,1,55,55,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,18,0,1
コードの分解
何が起こったのかについての詳細は次のとおりです。
外部エコー
echo -e $()$()
-e
印刷された結果が\n
最終結果から改行に変換されるように、最初に実行された2つのネストされたコマンドの結果をエコーします。
最初のコマンド
cut -d"=" -f1 OpenSimStats.txt | tr '\n' ',' | sed 's/,$/\\n/'
最初のネストされたコマンドです。=
すべてのテキストを1つの列(一連の区切り\n
値)に抽出するための区切り文字として使用されます。すべてを\n
次に置き換え、,
最後のコンマをaに戻します\n
(そうでない場合は、最後の値の後にカンマが続きます)。
コマンド自体は次のような出力を生成します。
TestreportsRootAgentCount,TestreportsChildAgentCount,TestreportsGCReportedMemory,TestreportsTotalObjectsCount,TestreportsTotalPhysicsFrameTime,TestreportsPhysicsUpdateFrameTime,TestreportsPrivateWorkingSetMemory,TestreportsTotalThreads,TestreportsTotalFrameTime,TestreportsTotalEventFrameTime,TestreportsLandFrameTime,TestreportsLastCompletedFrameAt,TestreportsTimeDilationMonitor,TestreportsSimFPSMonitor,TestreportsPhysicsFPSMonitor,TestreportsAgentUpdatesPerSecondMonitor,TestreportsActiveObjectCountMonitor,TestreportsActiveScriptsMonitor,TestreportsScriptEventsPerSecondMonitor,TestreportsInPacketsPerSecondMonitor,TestreportsOutPacketsPerSecondMonitor,TestreportsUnackedBytesMonitor,TestreportsPendingDownloadsMonitor,TestreportsPendingUploadsMonitor,TestreportsTotalFrameTimeMonitor,TestreportsNetFrameTimeMonitor,TestreportsPhysicsFrameTimeMonitor,TestreportsSimulationFrameTimeMonitor,TestreportsAgentFrameTimeMonitor,TestreportsImagesFrameTimeMonitor,TestreportsSpareFrameTimeMonitor,TestreportsLastReportedObjectUpdates,TestreportsSlowFrames
2番目の順序
sed -r 's/.*=([0-9]*).*/\1,/g' OpenSimStats.txt | tr -d '\n' | sed 's/,$//'
2番目のネストされたコマンドです。各行から目的の数字の周りのすべてのテキストを削除すると、数値列が生成されます(\n
--区切り値)。すべて\n
をに置き換えて、末尾の,
カンマを削除します。
結果は次のとおりです。
0,0,10,0,0,0,2144,0,89,0,0,25,1,55,55,0,0,0,0,0,0,0,0,0,18,0,0,0,0,0,18,0,1
上部の単一行は、これらの3つの部分を1つの行に結合して最終結果を生成します。