Скрипт оболочки для нормализации данных

Вопрос или проблема

У нас есть требование нормализовать данные … Поле элемента разделено запятыми и нерегулярно, и оно может содержать элементы от 0 до максимума (скажем, 100)

Входные данные:

key1|desc field|item1,item2,item3,item4|extra field
key2|desc field|item1,item2,item3|extra field

Выходные данные:

key1|desc field|item1|extra field
key1|desc field|item2|extra field
key1|desc field|item3|extra field
key1|desc field|item4|extra field
key2|desc field|item1|extra field
key2|desc field|item2|extra field
key2|desc field|item3|extra field

Существует ли способ, которым мы можем это достичь с помощью команды Unix или shell-скрипта? Пожалуйста, дайте совет.

Используя Miller (mlr) для “взрыва” подполей, разделённых запятыми, третьего поля во вводе, разделенном трубами:

$ mlr --nidx --fs pipe nest --evar , -f 3 file
key1|desc field|item1|extra field
key1|desc field|item2|extra field
key1|desc field|item3|extra field
key1|desc field|item4|extra field
key2|desc field|item1|extra field
key2|desc field|item2|extra field
key2|desc field|item3|extra field

Вот подход на Perl, который предполагает, что у вас никогда не будет | внутри каких-либо элементов:

$ perl -F'\|' -ane '@items = split(/,/,$F[2]); print join("|",@F[0,1],$_,@F[3..$#F]) for @items' file
key1|desc field|item1|extra field
key1|desc field|item2|extra field
key1|desc field|item3|extra field
key1|desc field|item4|extra field
key2|desc field|item1|extra field
key2|desc field|item2|extra field
key2|desc field|item3|extra field

Флаг -n говорит perl читать входные данные построчно и применять скрипт, указанный следующей командой -e, к каждой строке. Флаг -a говорит perl вести себя как awk и разбивать входные данные по символу, указанному в -F, и сохранять результат в массив @F.

Затем в скрипте мы разбиваем третье поле (нумерация начинается с 0, так что $F[2] — это третье поле) по запятым и сохраняем результат в массив @items. Затем для каждого элемента массива @items мы печатаем результат объединения первых двух полей с | (что дает нам начало оригинальной входной строки), затем текущий элемент (значение специальной переменной $_), и затем оставшуюся часть массива. Все объединяется с помощью |.

Вот очень короткое решение на python3; поместите его в файл (например, normalize.py), сделайте его исполняемым (chmod 755 normalize.py) и запустите его на своих входных данных (./normalize.py < your_input_data.file)

#!/usr/bin/env python3
from sys import stdin

for line in stdin:
  key, desc, items, extra = line.split("|")
  for item in items.split(","):
    if item:
      print(f"{key}|{desc}|{item}|{extra}")

Предположения: везде нет |, кроме как для разделителей столбцов, ровно 4 столбца на входную строку и в списке элементов нет запятых, кроме тех, которые разделяют элементы.


Обратите внимание, что ваш вопрос в основном кричит о том, что вам, вероятно, нужен лучший реляционный модель данных, чем это; в классическом дизайне реляционной базы данных вы бы создали две таблицы из этого:

  1. таблица “itemtypes” со столбцами ‘key’ (уникальный, первичный ключ), ‘description’ и ‘extra’
  2. таблица “items” со столбцом ‘item’ и столбцом ‘type_key’, который ссылается на ‘itemtypes.key’.

Используя awk:

awk -F'|' '
{
  split($3, items, ","); 
  for (i=1; i in items; i++) 
    print $1 "|" $2 "|" items[i] "|" $4
}'

Это разобьет 3-й столбец на массив с именем items, разделенный ,. Для каждого элемента в items он напечатает новую строку, используя значение каждого другого столбца из исходной строки.

Используя любой awk:

$ cat tst.awk
BEGIN { FS=OFS="|" }
{
    n = split($3, f, ",")
    for ( i=1; i<=n; i++ ) {
        $3 = f[i]
        print
    }
}

$ awk -f tst.awk file
key1|desc field|item1|extra field
key1|desc field|item2|extra field
key1|desc field|item3|extra field
key1|desc field|item4|extra field
key2|desc field|item1|extra field
key2|desc field|item2|extra field
key2|desc field|item3|extra field

Ответ или решение

Скрипт Shell для нормализации данных

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

1. Структура входных и выходных данных

Входные данные содержат строки с полями, разделенными символом |, где третье поле содержит элементы, разделенные запятыми:

Вход:

key1|desc field|item1,item2,item3,item4|extra field
key2|desc field|item1,item2,item3|extra field

Выход:

key1|desc field|item1|extra field
key1|desc field|item2|extra field
key1|desc field|item3|extra field
key1|desc field|item4|extra field
key2|desc field|item1|extra field
key2|desc field|item2|extra field
key2|desc field|item3|extra field

2. Решение с помощью awk

awk — это мощный инструмент для обработки текстовых файлов. Вот пример использования awk для достижения желаемого результата:

awk -F'|' '
{
  split($3, items, ",");  # Разделяем третье поле на массив items
  for (i = 1; i <= length(items); i++) 
    print $1 "|" $2 "|" items[i] "|" $4  # Выводим нужные поля
}' input_file

3. Решение с использованием Perl

Perl предоставляет мощные средства для работы с текстом. Пример решения на Perl:

perl -F'\|' -ane '@items = split(/,/,$F[2]); for (@items) { print join("|", $F[0], $F[1], $_, $F[3]), "\n" }' input_file

4. Использование Python

Python — еще один популярный инструмент для обработки данных. Вот как можно реализовать задачу на Python:

#!/usr/bin/env python3
from sys import stdin

for line in stdin:
    key, desc, items, extra = line.strip().split("|")
    for item in items.split(","):
        if item:  # Проверяем, что элемент не пустой
            print(f"{key}|{desc}|{item}|{extra}")

Сохраните этот код в файл, сделайте его исполняемым и запустите.

5. Использование Miller (mlr)

mlr — это инструмент для обработки и преобразования данных, который можно использовать следующим образом:

mlr --nidx --fs pipe nest --evar , -f 3 input_file

Заключение

В данной статье мы рассмотрели различные подходы к нормализации данных в формате, где поля разделены символами | и третье поле содержит элементы, разделенные запятыми. Вы можете выбрать любой из предложенных методов в зависимости от ваших предпочтений и условий. Инструменты, такие как awk, Perl, Python и Miller, предоставляют эффективные решения для решения данной задачи.

Для полноценной работы с данными рекомендуется рассмотреть возможность более строгой модели данных, например, использования реляционных баз данных, где данные могут быть структурированы более логично и эффективно.

Оцените материал
Добавить комментарий

Капча загружается...