Генерация JSON из данных, разделенных двоеточием в сценарии оболочки

Я бы не стал использовать --delete-after, потому что это заставляет rsync повторно сканировать список файлов. Лучшим вариантом на сегодняшний день является использование --delete-during (или --del для краткости). Если вы хотите сохранить эффект "удаления после" из-за проблем с ошибками ввода-вывода, используйте --delete-delay.

См. man-страницу для справки:

Некоторые опции требуют, чтобы rsync знал полный список файлов, поэтому эти опции отключают режим инкрементной рекурсии. К ним относятся: --delete-before, --delete-after, --prune-empty-dirs и --delay-updates. В связи с этим, режим удаления по умолчанию, когда вы указываете --delete, теперь --delete-during, когда оба конца не ниже 3.0.0 (используйте --del или --delete-during, чтобы запросить этот улучшенный режим удаления в явном виде). Смотрите также опцию --delete-delay опция, которая является лучшим выбором, чем использование --delete-after.

И, конечно, соответствующие разделы для каждого метода.

4
24.03.2017, 18:11
4 ответа

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

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

Вы используете группы захвата, чтобы захватить все между началом файла, вашим разделителем и концом файла, а затем просто манипулируете текстом вокруг этих групп. Каждая группа захвата обозначается "\#", где # - номер группы захвата, начиная с единицы и увеличиваясь на единицу для каждой группы.

Как уже упоминалось, вы также можете установить свой собственный разделитель. Bash имеет встроенную переменную под названием IFS (внутренний разделитель полей). По умолчанию IFS - пробел, но у вас есть возможность изменить ее. Я не буду показывать пример bash, так как он уже приводился и будет просто копией.

1
27.01.2020, 20:48
perl -F: -pale '
   @A = qw/randomId id userId dns status/;
   ($k, $_) = (0, "{" . join(",", map qq/"$A[$k++]":{"s":"$_"}/, @F) . "}");
' yourfile

Объяснение

@F содержит разделенные поля на : , которые затем сшиваются вместе с соответствующим массированием {"s": "fieldI"} и снабжены префиксом соответствующего элемента из массива @A . Все эти элементы объединены соединением на , и заключены в "{" ... "}". И вы сделали.

1
27.01.2020, 20:48

Этот блок 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 позволяет избежать всех \"-последовательностей, которые требует echo. Обратите внимание на обратную косую черту в конце строки, чтобы разделить ее.

BTW: Формат, который вы создаете, называется JSON, и могут существовать инструменты для его генерации (например, jq). Кроме того, он может потребовать собственного экранирования, если, например, ваши поля могут содержать двойные кавычки.

5
27.01.2020, 20:48

С perl :

perl -MJSON -F: -ple '@A = qw/randomId id userId dns status/; $_ = encode_json({map { shift @A => { "s" => $_ } } @F } )' input.csv
2
27.01.2020, 20:48

Теги

Похожие вопросы