以下のように複数行の記録されたデータがあります。
Name>Ami
Admin>2
Oper>1
Name>Sum
Admin>3
Total>2
Name>Tar
Admin>1
Oper>2
Name
今、これらのレコードをレコード要素とAdmin
「値」部分のみを含む単一のCSV行に縮小しようとしていますOper
。この例では、最終出力は次のようになります。
Ami,2,1
Sum,3,
Tar,1,2
出力は得られますが、その値を一致させて最初と2番目の列に入れてから3番目の列に入れたいpaste - - - -d,
ので、使用したくありません。Name
Admin
Oper
ベストアンサー1
あなたが望むようです
- 複数のレコード行を単一のCSV行に縮小します。
- レコード属性の値のみを印刷します
Name
。Admin
Oper
- これらの属性のいずれかが提供されていない「明示的な」空のフィールドを印刷します。
私は次のawk
プログラムをお勧めします:
awk -F'>' 'function printrec(){printf "%s,%s,%s\n",buf["Name"],buf["Admin"],buf["Oper"]}
(FNR>1 && $1=="Name"){printrec();delete buf}
{sub(/[[:space:]]*$/,"",$2); buf[$1]=$2}
END{printrec()}' input.txt
仕組みは次のとおりです。
入力ファイルのフィールド区切り記号はに設定されます
>
。レコードのすべての要素は連想配列に格納されます
buf
。printrec()
関連フィールドをカンマで区切って印刷する関数が定義されます。特定のキーが含まれていないbuf
場合、buf
参照は空の文字列として評価され、不足している属性の空のフィールドの要件を満たします。レコードがlineで始まるとします
Name
。このような行に出会えばいいえファイルの最初の行(FNR>1
)は、以前にバッファーされたレコードを印刷し、バッファーを再び消去します。buf
各行に対して、現在の属性は「配列インデックス」として「キー」部分を、配列値として「値」部分を使用して保存されます。ノート
sub()
入力例に含まれる「値」部分から末尾のスペースを削除する呼び出しを含めました。実際に空白がないと確信していれば、3行の該当部分は省略してもよい。ファイルの最後に、最後にバッファリングされたレコードが印刷されます。
この手順を例に適用すると、次の結果が表示されます。
Ami,2,1
Sum,3,
Tar,1,2
ノートdelete
配列を使用するにはGNUが必要ですawk
。味が変わったらawk
ぜひお試しください
split("",buf)
回避策として。
また、レコードに属性の複数のインスタンスが含まれている場合(Name
常にレコードの先頭と見なされない限り)、後続の発生は以前の発生を上書きします。