前の行に基づいて行を更新する

前の行に基づいて行を更新する

awkに慣れていないので質問があります。 sar -d出力で生成されたcsvファイルをcsvスタイルに変換しました。

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
,iscsi0,0,0.0,0,0,0.0,0.0
,scsi_vhc,0,0.0,0,0,0.0,0.0
,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
,iscsi0,0,0.0,0,0,0.0,0.0
,scsi_vhc,0,0.0,0,0,0.0,0.0
,nfs1,0,0.0,0,0,0.0,0.0

これに変換したい

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0

試してみましたが、awkは1行ずつ読み取るので、前の行の値を保持する方法がわかりません。私が持っていることがうまくいくことを願っています。私が望む結果を得るために何が必要かを学びます。私はawkを試してみましたが、これはsedを使用するか、カスタムシェルスクリプトを使用して可能でなければならないと思います(この部分は実行しないようにしています)。

#!/usr/bin/awk -f
BEGIN {
        FS=",";
}
{
        print $1
        if ($1 != "") {
                mydate=$1;
                print $0;
        }
        else {
                print $mydate","$0;
        }
}

Solaris 11.1 システムを実行しています。

答え1

入力に空白行があるように見えるため、時間が少し長くなります。以下はあなたに役立ちます。

awk -F'[, ]' '{if (NF!=0 && $1=="") {$1=prev} prev=$1}1' OFS=, inputfile

アイデアは、フィールド,とスペースを分割することです(後者は入力の最初の行を処理することです)。最初のフィールドが空であることを確認するそしてフィールド数がゼロでない場合(空行を処理するために)、最初のフィールドは以前に保存された最初のフィールドに置き換えられます。

あなたの入力に対して以下が生成されます。

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0

答え2

そしてsed

sed '/^[0-9]/{               # if line starts with digit
h                            # overwrite hold buffer with pattern space content
s/\([^,]*\),.*/\1/           # extract timestamp
x                            # exchange: put the original line back into pattern
}                            # space and the timestamp in hold space
/^,/{                        # if line starts with a comma
G                            # append hold space (timestamp) to pattern space
s/\(.*\)\n\(.*\)/\2\1/       # swap the initial line content and the timestamp 
}' infile

一行:

sed -e'/^[0-9]/{h;s/\([^,]*\),.*/\1/;x' -e\} -e'/^,/{G;s/\(.*\)\n\(.*\)/\2\1/' -e\} infile

答え3

その他sed:

sed '$!N;/\n,/s/\([^,]*\).*\n/&\1/;P;D' <in >out

!最後の入力行ではない各入力行の場合$、ewline文字の前に追加の入力行がパターンスペースに追加さsedれます。次に、非コンマ文字の最初のセットをewlineの後のコンマの直前のスペースにコピーする代替操作を試みます。そうでなければ悪くないと思います。N\ns///^,\n

sedその後、パターンスペースの最初の行Pに印刷して同じ内容を削除し、一番上から始まる次の入力行のペアでループを再開します。\nD

出力

12:33:41        unix,restarts
12:35:00,lofi4096,0,0.0,0,0,0.0,0.0
12:35:00,iscsi0,0,0.0,0,0,0.0,0.0
12:35:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:35:00,nfs1,0,0.0,0,0,0.0,0.0

12:45:00,lofi4096,0,0.0,0,0,0.0,0.0
12:45:00,iscsi0,0,0.0,0,0,0.0,0.0
12:45:00,scsi_vhc,0,0.0,0,0,0.0,0.0
12:45:00,nfs1,0,0.0,0,0,0.0,0.0

関連情報