Извлечение данных из CSV в сценарии оболочки (Sed, AWK, Grep?) - PullRequest
1 голос
/ 21 сентября 2009

Мне нужно извлечь некоторые данные из файла CSV. CSV - это файл из 2 столбцов с несколькими записями. Первый столбец - это дата, второй столбец - это данные, которые необходимо извлечь. Первая строка файла CSV - это заголовки столбцов, поэтому их можно пропустить. И я уже создал заголовок столбца для файла csv извлеченных данных, поэтому в этом нет необходимости, я просто использую >> для импорта в него данных.

Вот 1 запись / строка (из многих) в файле CSV:

"2009-09-20 00:12:37","a:2:{s:15:""info_buyRequest"";a:5:{s:4:""uenc"";s:116:""aHR0cDovL3N0b3JlLmZvcmdldGhhbmdvdmVycy5jb20vcGF0Y2hlcy9pbmRpdmlkdWFsLXBhdGNoZXMvZnJlZS1zYW1wbGUuaHRtbD9fX19TSUQ9VQ,,"";s:7:""product"";s:1:""1"";s:15:""related_product"";s:0:"""";s:7:""options"";a:13:{i:17;s:2:""59"";i:16;s:2:""50"";i:15;s:2:""49"";i:14;s:2:""47"";i:13;s:2:""41"";i:12;s:2:""34"";i:11;s:2:""25"";i:10;s:2:""23"";i:9;s:2:""19"";i:8;s:2:""17"";i:7;s:2:""12"";i:6;s:1:""9"";i:5;s:1:""5"";}s:3:""qty"";i:1;}s:7:""options"";a:13:{i:0;a:7:{s:5:""label"";s:25:""How did you hear about us"";s:5:""value"";s:22:""Friend / Family Member"";s:11:""print_value"";s:22:""Friend / Family Member"";s:9:""option_id"";s:2:""17"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:2:""59"";s:11:""custom_view"";b:0;}i:1;a:7:{s:5:""label"";s:3:""Age"";s:5:""value"";s:5:""21-24"";s:11:""print_value"";s:5:""21-24"";s:9:""option_id"";s:2:""16"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:2:""50"";s:11:""custom_view"";b:0;}i:2;a:7:{s:5:""label"";s:14:""Marital Status"";s:5:""value"";s:9:""UnMarried"";s:11:""print_value"";s:9:""UnMarried"";s:9:""option_id"";s:2:""15"";s:11:""option_type"";s:5:""radio"";s:12:""option_value"";s:2:""49"";s:11:""custom_view"";b:0;}i:3;a:7:{s:5:""label"";s:3:""Sex"";s:5:""value"";s:6:""Female"";s:11:""print_value"";s:6:""Female"";s:9:""option_id"";s:2:""14"";s:11:""option_type"";s:5:""radio"";s:12:""option_value"";s:2:""47"";s:11:""custom_view"";b:0;}i:4;a:7:{s:5:""label"";s:10:""Occupation"";s:5:""value"";s:7:""Student"";s:11:""print_value"";s:7:""Student"";s:9:""option_id"";s:2:""13"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:2:""41"";s:11:""custom_view"";b:0;}i:5;a:7:{s:5:""label"";s:9:""Education"";s:5:""value"";s:16:""College Graduate"";s:11:""print_value"";s:16:""College Graduate"";s:9:""option_id"";s:2:""12"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:2:""34"";s:11:""custom_view"";b:0;}i:6;a:7:{s:5:""label"";s:16:""Household Income"";s:5:""value"";s:7:""30K-50K"";s:11:""print_value"";s:7:""30K-50K"";s:9:""option_id"";s:2:""11"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:2:""25"";s:11:""custom_view"";b:0;}i:7;a:7:{s:5:""label"";s:23:""Do You Take Supplements"";s:5:""value"";s:2:""No"";s:11:""print_value"";s:2:""No"";s:9:""option_id"";s:2:""10"";s:11:""option_type"";s:5:""radio"";s:12:""option_value"";s:2:""23"";s:11:""custom_view"";b:0;}i:8;a:7:{s:5:""label"";s:40:""How would you rank your typical hangover"";s:5:""value"";s:4:""Mild"";s:11:""print_value"";s:4:""Mild"";s:9:""option_id"";s:1:""9"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:2:""19"";s:11:""custom_view"";b:0;}i:9;a:7:{s:5:""label"";s:51:""What type of establishments do you typically prefer"";s:5:""value"";s:10:""Nightclubs"";s:11:""print_value"";s:10:""Nightclubs"";s:9:""option_id"";s:1:""8"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:2:""17"";s:11:""custom_view"";b:0;}i:10;a:7:{s:5:""label"";s:40:""How often do you usually go out per week"";s:5:""value"";s:3:""1-2"";s:11:""print_value"";s:3:""1-2"";s:9:""option_id"";s:1:""7"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:2:""12"";s:11:""custom_view"";b:0;}i:11;a:7:{s:5:""label"";s:49:""How many drinks do you typically consume per week"";s:5:""value"";s:3:""6-8"";s:11:""print_value"";s:3:""6-8"";s:9:""option_id"";s:1:""6"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:1:""9"";s:11:""custom_view"";b:0;}i:12;a:7:{s:5:""label"";s:53:""How would you prefer to buy our Products"";s:5:""value"";s:6:""Online"";s:11:""print_value"";s:6:""Online"";s:9:""option_id"";s:1:""5"";s:11:""option_type"";s:9:""drop_down"";s:12:""option_value"";s:1:""5"";s:11:""custom_view"";b:0;}}}"

Выходные данные должны быть найдены здесь:

  • "" print_value "; s:? :" " {DATA} " "* +1013 *

Было ли ? числом, а {ДАННЫЕ} - извлекаемыми данными.

Таким образом, вывод для этой записи 1 будет:

"2009-09-20 00:12:37","Friend / Family Member","21-24","UnMarried","Female","Student","College Graduate","30K-50K","No","Mild","Nightclubs","1-2","6-8","Online"

Я не опытен в Sed, AWK или Grep, но я знаю, что это можно сделать с помощью одного из этих инструментов, если не всех трех. Любая помощь или толчки в правильном направлении будут с благодарностью.

Ответы [ 3 ]

2 голосов
/ 21 сентября 2009

Я предлагаю вам использовать PHP для десериализации структуры. Тем не менее, вот быстрая и грязная версия того, что вы хотите, используя sed и tr . Конечно, вы можете сделать это намного лучше:

cat file.csv | \
tr ",;" "\n" | \
sed -e 's/[asbi]:[0-9]*[:]*//g' -e '/^[{}]/d' -e 's/""//g' -e '/^"{/d' | \
sed -n -e '/^"/p' -e '/^print_value$/,/^option_id$/p' | \
sed -e '/^option_id/d' -e '/^print_value/d' -e 's/^"\(.*\)"$/\1/' | \
tr "\n" "," | \
sed -e 's/,\([0-9]*-[0-9]*-[0-9]*\)/\n\1/g' -e 's/,$//' | \
sed -e 's/^/"/g' -e 's/$/"/g' -e 's/,/","/g'

Объяснение:

  • разделяется запятыми и точками с запятой
  • удалить удалить синтаксис структуры php s: X: Y, b: X, ... и удалить строки, начинающиеся с {или} или "{
  • извлечь раздел из print_value до следующего option_id, также сохранить дату (строка начинается с ")
  • удалить эти метки (печать и опция) и удалить цитаты вокруг даты
  • заключить все строки в запятые
  • отдельные строки (начиная с шаблона даты) и удаление лишней запятой в конце
  • добавить кавычки вокруг всех полей

Ух ты, я знаю, это смущает :) 1026 *

0 голосов
/ 03 октября 2011

Вот sed oner:

sed -nr 's/^([^,]+),(.*)$/\2@%@\1/;:a;s/""print_value"";s:[0-9]+:""([^"]+)""(.*)$/\2,"\1"/;ta;s/^.*@%@//p' <source

В основном извлекаем данные и добавляем их в конец строки, используя уникальный разделитель '@% @'.

При сбое конструкции цикла / замены (т. Е. Больше нет данных) отбрасывать то, что осталось от исходной строки, оставляя данные в хорошем формате.

0 голосов
/ 21 сентября 2009

Вот мой ответ:


cat TestData \
    | grep -o -P "print_value\"\";.*?:\"\".*?\"\";" \
    | perl -pe 's|print_value.*:\"\"(.*?)\"\";|\1|'

В первой строке отображаются данные (сохраненные в TestData).

Вторая строка просит grep отделить каждое совпадение от print_value до ближайшего '"";'. Обратите внимание, что я использую '. *?' для не жадного совпадения (необходимо использовать с ним '-P').

В последней строке используется perl для удаления всего ненужного. Посмотрите, что я использую '(. *?)', Чтобы найти нужную группу, и "\ 1", чтобы показать группу.

Надеюсь, это поможет.

...