web-dev-qa-db-ja.com

シェルスクリプトでコロンで区切られたデータからJSONを生成する

私はこのようなファイルを持っています

103710:v2HAbAFH029324:[email protected]:localhost:Sent
103821:CCFE5609E3:[email protected]:localhost:bounced
103922:DFF19609E2:[email protected]:localhost:Deferred

これをに変更する必要があります

{"randomId":{"s":"103710"},"id":{"s":"v2HAbAFH029324"},"userId":{"s":"[email protected]"},"dns":{"s":"localhost"},"status":{"s":"Sent"}}
{"randomId":{"s":"103821"},"id":{"s":"CCFE5609E3"},"userId":{"s":"[email protected]"},"dns":{"s":"localhost"},"status":{"s":"bounced"}}
{"randomId":{"s":"103922"},"id":{"s":"DFF19609E2"},"userId":{"s":"[email protected]"},"dns":{"s":"localhost"},"status":{"s":"Deferred"}}

私はこのようなコードを考えています

while read line
do     
        sed -i 's/^/{"randomId":{"s":"/' test
        echo $line

        echo $line | grep -q ":"
        [ $? -eq 0 ] && echo "/"{"id":{"s":/"
        [ $? -eq 1 ] && echo "/",{"userId":{"s":/"
        [ $? -eq 2 ] && echo "/",{"Host":{"s":/"
        [ $? -eq 3 ] && echo "/",{"status":{"s":/"
        echo "$line | " ";
done < test

{"id":{"s":の最初の発生を追加し、次に{"userId":{"s":を追加します。

4
kumar babu

データは区切られていて読みやすいため、これを行うにはいくつかの方法があります。 Sedは、データを1行で解析し、変更を出力できます。

sed -r -i 's/^(.*):(.*):(.*):(.*):(.*)$/{"randomId":{"s":"\1"},"id":{"s":"\2"},"userId":{"s":"\3"},"dns":{"s":"\4"},"status":{"s":"\5"}}/' input.txt

キャプチャグループを使用して、ファイルの先頭、区切り文字、ファイルの末尾の間のすべてをキャプチャし、それらのグループの周囲のテキストを操作します。すべてのキャプチャグループは「\#」で参照されます。ここで、#は、1から始まり、グループごとに1ずつ増加するキャプチャグループの番号です。

すでに述べたように、独自の区切り文字を設定することもできます。 Bashには、IFS(内部フィールドセパレーター)と呼ばれる組み込み変数があります。 IFSのデフォルトは空白ですが、変更することができます。すでに与えられているので、bashの例は示しません。これは、そのコピーにすぎません。

1

そのgrep/echoブロックは、何の役にも立ちません。 $?一度設定されます。フィールドを繰り返し処理することはありません。

ありがたいことに、これを行うにははるかに簡単な方法があるようです。フィールドを変数に分割するだけです。ありがたいことに、readはあなたのためにこれを行うことができます:

while IFS=':' read -r randomid id userid dns status; do
    printf '{"randomId":{"s":"%s"},"id":{"s":"%s"},"userId":{"s":"%s"},"dns":{"s":"%s"},"status":{"s":"%s"}}\n' \
           "$randomid" "$id" "$userid" "$dns" "$status"
done

使い慣れたprintfの代わりにechoを使用すると、すべての\"- sequences echoが必要です。行を区切るために、行末のバックスラッシュに注意してください。

ところで:あなたが作成しているフォーマットはJSONと呼ばれ、それを生成するのに役立つツールがあるかもしれません(例えば、 jq )。また、たとえばフィールドに二重引用符を含めることができる場合は、独自のエスケープが必要になる場合があります。

5
derobert

Perlの場合:

Perl -MJSON -F: -ple '@A = qw/randomId id userId dns status/; $_ = encode_json({map { shift @A => { "s" => $_ } } @F } )' input.csv
2
Satō Katsura
Perl -F: -pale '
   @A = qw/randomId id userId dns status/;
   ($k, $_) = (0, "{" . join(",", map qq/"$A[$k++]":{"s":"$_"}/, @F) . "}");
' yourfile

説明

@Fは、:で分割されたフィールドを保持します。これらのフィールドは、適切なマッサージ{"s":"fieldI"}で縫い合わされ、配列@Aの対応する要素が前に付けられます。これらの要素はすべて、,joinによってまとめられ、「{」...「}」で囲まれます。これで完了です。

1
user218374