2013-03-25 2 views
4

У меня есть следующие записи:Разделительные выходных записей в AWK без завершающего разделителя

31 Stockholm 
42 Talin 
34 Helsinki 
24 Moscow 
15 Tokyo 

И я хочу, чтобы преобразовать его в формат JSON с AWK. Используя этот код:

#!/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 
} 
+0

Я рад, что вы задали этот вопрос, учась использовать awk, так как @ ed-morton и его блестящий взлом обработки разделителя записей заставили лампочку погасить мою связанную с этим проблему. –

ответ

9

Упомяните о какой-либо обратной связи по вашему опубликованному сценарию?

#!/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 
} 
+2

Пустое значение 'sep' для первой записи является гением. – Samveen

2

У вас есть несколько вариантов. Легко можно было бы добавить запятую в предыдущей строке, как вы собираетесь написать новую строку:

  • Установить переменную first = 1 в вашем BEGIN.

  • Когда начнется печать строки, отметьте first. Если это 1, просто установите его на 0. Если 0 распечатывает запятую и новая строка:

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

    Смысл этого, чтобы не подвергать лишнюю запятую в начале списка.

  • Используйте printf("%s", ...) вместо print ..., чтобы избежать печати новой строки при печати записи.

  • Добавить дополнительную строку перед закрывающей фигурной скобкой, как: print "\n}";

Кроме того, обратите внимание, что если вы не заботитесь об эстетике, JSON на самом деле не требует перевода строки между элементами и т.д. Вы могли бы просто вывести одну большую линию для всей энчилады.

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 
} 
+1

Я ценю помощь, но я решил решить эту проблему с помощью AWK, чтобы изучить инструмент. У меня есть сценарий Nodejs, который выполняет работу должным образом. – AlexStack

1

Вы должны действительно использовать json parser но вот как с 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 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^