Создание шаблонов в yaml из CSV-файла

Busybox — это не дистрибутив, на нем нет менеджера пакетов. Он также не имеет разделяемых библиотек по умолчанию (*), поэтому вам нужно статически компоновать все, что в основном означает перекомпиляцию всего, что вы хотите поместить в него.

(*)Возможно, в вашей конкретной производной Busybox есть разделяемые библиотеки, но у вас не будет заголовков для них, поэтому вы также не сможете их использовать.

1
02.10.2021, 18:34
1 ответ

Это gawkрешение было протестировано на GNU Awk v5.1.0.

Он состоит из сценария Bash, который принимает два входных файла :yaml_template(, указанных в OP):

$ cat yaml_template
number: {{NUMBER}}
  name: {{NAME}}
  region: {{REGION}}
  storenum: {{STORENUM}}
  clients: {{CLIENTS}}
  tags: {{TAGS}}


storename: {{STORENAME}}
employee: {{EMPLOYEE}}
products: {{PRODUCTS}}

и data.csv(, предложенные @cas в его ответе):

$ cat data.csv
NUMBER,NAME,REGION,STORENUM,CLIENTS,TAGS,STORENAME,EMPLOYEE,PRODUCTS
37579922,Store1,New York,32,100,stores,Store newyork,10,200
2,Store2,Somewhere,2,100,"tag1,tag2,tag3",Somewhere Store,5,10
3,Store3,Elsewhere,3,100,"tag1,tag3",Elsewhere Store,3,100

Сценарий Bash, yamlit.shделается исполняемым (с помощью cmd$ chmod ug+x yamlit.sh):

$ cat yamlit.sh
#!/usr/bin/env bash
gawk -F"[,:]" '
    FNR==NR {
        match($0,/[^[:blank:]]+/); i++;
        if (RSTART-1 < 0) {$1="";null++; teenar[i] = ""} else {$1 = substr($1,RSTART); teenar[i] = $1};
        teenof[$1] = RSTART - 1;
        next;
    }
    FNR==1 {nteen=i; ncol=split(tolower($0), colhead, ",");next;}
    {
    for (i=1; i<=nteen; i++) {
        offset=teenof[teenar[i]];
        if (offset >= 0) {
            patsplit($0,datafield,"([^,]*)|(\"[^\"]*\")")
            for (j=1; j<=ncol; j++) {
                if (tolower(teenar[i]) == colhead[j]) {
                    printf "%*s: %s\n", length(teenar[i]) + offset, teenar[i], datafield[j];
                    }
                }
            }
        else {print ""}
        }
    printf "\n%s\n", "=========================="
    }' "$1" "$2"

Скрипт при запуске из терминала дает результат:

$ yamlit.sh yaml_template data.csv
number: 37579922
  name: Store1
  region: New York
  storenum: 32
  clients: 100
  tags: stores


storename: Store newyork
employee: 10
products: 200

==========================
number: 2
  name: Store2
  region: Somewhere
  storenum: 2
  clients: 100
  tags: "tag1,tag2,tag3"


storename: Somewhere Store
employee: 5
products: 10

==========================
number: 3
  name: Store3
  region: Elsewhere
  storenum: 3
  clients: 100
  tags: "tag1,tag3"


storename: Elsewhere Store
employee: 3
products: 100

==========================

Слово пояснения:

  • Скрипт выводит вывод на терминал, но вывод можно легко перенаправить в файл, например. из CLI :$ yamlit.sh yaml_template data.csv >| yaml_out,
  • он скрупулезно соблюдает формат и структуру, предоставленные шаблоном yaml. Любая ошибка форматирования в шаблоне будет отображаться в выводе. Это включает в себя любые ошибочные пробелы (, то есть ошибочные отступы )и пустые строки,
  • он учитывает порядок, в котором предоставляются записи шаблона, независимо от порядка столбцов в файле данных data.csv,
  • шаблоны могут быть настолько сложными и иметь столько вложенных уровней, сколько необходимо ,
  • сопоставление ключей ввода шаблона и заголовков столбцов данных не зависит от регистра -.

Что можно добавить?
Функции, которые было бы тривиально добавить в скрипт, включают:

  • перенаправление вывода "yaml" каждой записи файла данных либо в один файл на диске, либо в столько отдельных выходных файлов, сколько существует записей данных (строк ), не считая заголовка файла.
  • выполняются проверки на наличие несоответствия данных между data.csvи ключами ввода шаблона yaml в файле шаблона

Код:

  • первый блок FNR==NR {...}вычисляет:
    • количество (пустых и не-пустых )строк в файле шаблона,
    • отступ каждой строки, сохраненный в массиве :teenof, сокращение от "TEMplate ENTry OFFset". Отрицательные значения указывают на пустую строку в файле шаблона.
    • Ключ входа в шаблон (первое поле записи )в другом массиве :teenar, сокращение от «TEMplate ENtry ARray».
  • Второй блок FNR==1 {...}помещает каждый заголовок столбца файла data.csvв третий массив colhead.
  • третий и последний блок {...}делает несколько вещей:
    • зацикливается на клавишах ввода шаблона (в нижнем регистре ),
    • для положительных или нулевых отступов:
      • он разбивает каждую data.csvзапись файла в соответствии с регулярным выражением поля, способным определить, состоит ли какое-либо поле в записи из строки в кавычках, содержащей другие разделители полей (здесь,)или нет. Компоненты, полученные в результате разделения, помещаются в четвертый массив :datafield.
      • он выполняет вложенный -цикл по заголовкам столбцов файла данных, чтобы найти совпадение с записью шаблона; Если он найден, он печатает соответствующую строку, соблюдая отступ, указанный в шаблоне yaml.
    • для отрицательных отступов печатается пустая строка, таким образом, соблюдая исходную последовательность шаблона, в которой он включает одну или несколько пустых строк.

Критика:

  • Используются два вложенных цикла, что даже для awkдалеко не идеально с вычислительной точки зрения. Сложность O (n^2 ). Однако это сделало возможным обобщение решения с точки зрения файлов data.csv, имеющих произвольный порядок столбцов относительно порядка записей в файле шаблона yaml. Я не стал тратить время на поиск другого решения. Не уверен, что есть лучше с awk...
  • .
  • В общей сложности используются 4 массива GNU Awk, которые для файлов «очень больших» или «массивных», скажем, со многими столбцами и множеством записей (или строк )могут занимать много памяти. соответствующие массивы(teenofи teenar), построенные из шаблонов yaml, предположительно с таким количеством записей, как есть столбцы данных. Из этих 4 массивов только один(datafield)очищается и перестраивается для каждой записи файла data.csv. Остальные статичны. Тем не менее, я не уверен, что сжатие массива Gawk новым перераспределяет память так же эффективно, как C для удаленной/переобъявленной переменной массива. Я оставляю это для других, более осведомленных, чем я, чтобы прокомментировать.

ХТН.

0
03.10.2021, 21:15

Теги

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