このサイトを初めて使用する際に、この質問をして申し訳ありません。
次の形式のテキストファイルがあります。
file: abc
value: 123
value: 234
value: 567
file: def
value: 999
file: ghi
value: 123
value: 999
file
私の目標は、このテキストを各行に対して値が繰り返されるCSV形式に変換するbashスクリプトを作成することです。上記のデータは次のようになります。
abc,123
abc,234
abc,567
def,999
ghi,123
ghi,999
試してみましたが、sed
複数行のファイル名を覚える方法がわかりません。簡単になるかもしれませんが、awk
まだ目が覚めていません。
ご協力ありがとうございます!
ベストアンサー1
これらのキーが見つかるたびに、次のawk
コマンドはawk
変数をfile
キー値に設定しますfile
(キーは行の最初のフィールド、値は2番目のフィールドです)。現在行にfile
キーがない場合は、変数の現在値がfile
現在行の値とともに出力されます。
$ awk -F ': ' 'BEGIN { OFS="," } $1 == "file" { file = $2; next } { print file, $2 }' file
abc,123
abc,234
abc,567
def,999
ghi,123
ghi,999
これはCSV値を正しく引用しようとする試みではなく、フィールド区切り文字:
(コロン+スペース)を含む値がないと仮定します。
そしてsed
:
sed -n \
-e '/^file: / { s///; h; }' \
-e '/^value: / { s///; G; s/\(.*\)\n\(.*\)/\2,\1/p; }' file
file:
行が見つかると、file:
プレフィックス文字列が削除され、残りは予約済みスペースに保存されます。
value:
行が見つかると、value:
プレフィックス文字列が削除され、予約済みスペースのテキストがリテラル改行文字を区切り文字としてバッファの末尾に追加されます。バッファの改行で区切られた部分が置き換えられ(改行がコンマで置き換えられて)出力されます。
結果は予想通りです。
key:
最初の文字列の後の値にコロン+スペースを含めることができないという制限はありません。同様に、最終出力にはCSVテキストの特別なエンコーディングがないため、カンマと二重引用符を含むフィールドはCSVパーサーを混乱させます。
以下は、ソースファイルの各行の間に空行を追加することによって入力を変更します。これにより、ファイルは有効な「XTAB」ファイルになり、:
キーと値の区切り文字として機能します。その後、mlr
CSVの特別な引用規則を理解し、XTAB形式を読むことができるMiller()が読み取られます。
Millerは出力からレコードを読み取り、awk
データに「パディング」操作を実行して、レコードがない各レコードに以前のfile
値を割り当てます。file
その後の「フィルタ」アクションは、フィールドを持たないすべての履歴を削除しますvalue
。
これにより、CSVヘッダーなしでデータが出力されます。
awk '{ print; print "" }' file |
mlr --ixtab --ips ': ' \
--ocsv --headerless-csv-output \
fill-down -f file then filter -x 'is_absent($value)'
入力にコンマと引用符が含まれていても、完全に互換性のあるCSV出力が正しく生成されることを示すためにテストデータを修正しました。
$ cat file
file: test: here's a test
value: this is, the value
value: another so called "value"
file: abc
value: 123
value: 234
value: 567
file: def
value: 999
file: ghi
value: 123
value: 999
$ awk '{ print; print "" }' file | mlr --ixtab --ips ': ' --ocsv --headerless-csv-output fill-down -f file then filter -x 'is_absent($value)'
"this is, the value",test: here's a test
"another so called ""value""",test: here's a test
123,abc
234,abc
567,abc
999,def
123,ghi
999,ghi