6

私は次の記録を持っています:

31 Stockholm
42 Talin
34 Helsinki
24 Moscow
15 Tokyo

そして、AWKでJSONに変換したいと思います。このコードの使用:

#!/usr/bin/awk
BEGIN {
    print "{";
    FS=" ";
    ORS=",\n";
    OFS=":";
};

{    
    if ( !a[city]++ && NR > 1 ) {
        key = $2;
        value = $1;
        print "\"" key "\"", value;
    }
};

END {
    ORS="\n";
    OFS=" ";
    print "\b\b}";
};

私にこれを与えます:

{
"Stockholm":31,
"Talin":42,
"Helsinki":34,
"Moscow":24,
"Tokyo":15, <--- I don't want this comma
}

問題は、最後のデータ行の末尾にコンマがあることです。JSON出力が受け入れられなくなります。この出力を取得するにはどうすればよいですか?

{
"Stockholm":31,
"Talin":42,
"Helsinki":34,
"Moscow":24,
"Tokyo":15
}
4

4 に答える 4

10

投稿したスクリプトに関するフィードバックをお聞かせください。

#!/usr/bin/awk        # Just be aware that on Solaris this will be old, broken awk which you must never use
BEGIN {
    print "{";        # On this and every other line, the trailing semi-colon is a pointless null-statement, remove all of these.
    FS=" ";           # This is setting FS to the value it already has so remove it.
    ORS=",\n";
    OFS=":";
};

{
    if ( !a[city]++ && NR > 1 ) {      # awk consists of <condition>{<action} segments so move this condition out to the condition part
                                       # also, you never populate a variable named "city" so `!a[city]++` won't behave sensibly.
        key = $2;
        value = $1;
        print "\"" key "\"", value;
    }
};

END {
    ORS="\n";                          # no need to set ORS and OFS when the script will no longer use them.
    OFS=" ";
    print "\b\b}";                     # why would you want to print a backspace???
};

したがって、元のスクリプトは次のように記述されている必要があります。

#!/usr/bin/awk
BEGIN {
    print "{"
    ORS=",\n"
    OFS=":"
}

!a[city]++ && (NR > 1) {    
    key = $2
    value = $1
    print "\"" key "\"", value
}

END {
    print "}"
}

ただし、投稿された入力を投稿された出力に変換するスクリプトを実際に作成する方法は次のとおりです。

$ cat file
31 Stockholm
42 Talin
34 Helsinki
24 Moscow
15 Tokyo
$
$ awk 'BEGIN{print "{"} {printf "%s\"%s\":%s",sep,$2,$1; sep=",\n"} END{print "\n}"}' file
{
"Stockholm":31,
"Talin":42,
"Helsinki":34,
"Moscow":24,
"Tokyo":15
}
于 2013-03-26T01:06:31.300 に答える
2

いくつかの選択肢があります。簡単な方法は、新しい行を書き出そうとしているときに、前の行のコンマを追加することです。

  • に変数を設定first = 1しますBEGIN

  • 行を印刷するときは、を確認してくださいfirst。の場合は1、に設定し0ます。0カンマと改行を出力する場合:

    if (first) { first = 0; } else { print ","; }
    

    これのポイントは、リストの先頭に余分なコンマを入れないようにすることです。

  • レコードを印刷するときに改行を回避できるように、printf("%s", ...)の代わりに使用します。print ...

  • 次のように、中括弧の前に改行を追加します。print "\n}";

また、美学を気にしないのであれば、JSONはアイテム間の改行などを実際には必要としないことに注意してください。エンチラーダ全体に対して1つの大きな行を出力するだけで済みます。

于 2013-03-25T20:00:04.647 に答える
1

あなたは本当にjsonパーサーを使うべきですが、これがその方法awkです:

BEGIN {
    print "{"    
}
NR==1{
    s= "\""$2"\":"$1
    next
}
{
    s=s",\n\""$2"\":"$1
}
END {
    printf "%s\n%s",s,"}"
}

出力:

{
"Stockholm":31,
"Talin":42,
"Helsinki":34,
"Moscow":24,
"Tokyo":15
}
于 2013-03-25T20:20:29.873 に答える
0

jsonパーサーを使用してみませんか?何かを強制awkしないでください。そうするように設計されていません。これが使用する解決策pythonです:

import json

d = {}
with open("file") as f:
    for line in f:
       (val, key) = line.split()
       d[key] = int(val)

print json.dumps(d,indent=0)

これは以下を出力します:

{
"Helsinki": 34, 
"Moscow": 24, 
"Stockholm": 31, 
"Talin": 42, 
"Tokyo": 15
}
于 2013-03-25T20:03:55.173 に答える