Форум русскоязычного сообщества Ubuntu


Хотите сделать посильный вклад в развитие Ubuntu и русскоязычного сообщества?
Помогите нам с документацией!

Автор Тема: Помогите с парсингом данных из файла средствами консоли(bash, awk)  (Прочитано 500 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн fill.sa

  • Автор темы
  • Любитель
  • *
  • Сообщений: 77
    • Просмотр профиля
Товарищи гуру, поделитесь советом.
Значиться имеется csv файл с данными на пару тыс строк и все это сейчас парситься через разные костыли и в конце через exel.
Хочется переделать, чтобы все делалось запуском одного скрипта из консоли.

Сам файл имеет строки такого вида:
"инфа";"инфа";"инфа";"инфа";"инфа";"инфа";"инфа";"НОМЕР_ОБОРУДОВАНИЯ";"инфа";"инфа";"инфа";"инфа";"инфа";"инфа";"инфа";"инфа";"СУММА";"инфа"
Задача получить два столбца "НОМЕР_ОБОРУДОВАНИЯ" "СУММА" (8 и 17 столбцы), при условии что в "НОМЕР_ОБОРУДОВАНИЯ" номера повторяются и соответственно сумма должна быть просумирована по всем повторам.

Смог набросать такой код, но цикл работает ну оооочень долго и по итогу получаю белеберду а не нужные столбцы.

grep -v -e "test" $INFILE | awk -F ";" '{print $8 " " ,$17 }' > $TMPFILE2


for x in `cat $TMPFILE2 | awk -F " " '{print$1}'`;
do
grep $x $TMPFILE2 | awk -F " " '{sum+=$2;} END{print $x " ", $sum}' >> "$VKLADKA3FILE"
sed -i "/$x/d" $TMPFILE2
done

cat $TMPFILE2 >> "$VKLADKA3FILE"
sed -i "/^$/d" "$VKLADKA3FILE"



« Последнее редактирование: 30 Июнь 2018, 17:33:16 от fill.sa »

Оффлайн inkblack

  • Старожил
  • *
  • Сообщений: 1216
    • Просмотр профиля
1. Я думаю, что надо _один раз_ скормить этот файл awk — он вполне позволяет делать сложные обработки данных.
Не надо сто раз вызывать grep в цикле.

2. Что-то вы не договариваете. Зачем grep -v -e "test"? В файле есть что-то еще?

3. Что надо сделать?

"и";...;"и"; "100" ;"и";...;"и"; "20" ;"и"
"и";...;"и"; "100" ;"и";...;"и"; "30" ;"и"
"и";...;"и"; "999" ;"и";...;"и"; "11" ;"и"

=>

100 50
999 11


— так? (Номер == 100 -> 20+30, Номер == 999 -> 11)

Прислали бы примерчик файла, хотя бы строк 10.
Делюсь знаниями, но их у меня мало!

Оффлайн fill.sa

  • Автор темы
  • Любитель
  • *
  • Сообщений: 77
    • Просмотр профиля
1.Что-то познаний не хватило, вот и пришел за советом. Больно мудреный этот awk )

2.Да, в файле есть строки с пробным оборудованием(test подписывается) оно не должно учитываться, во и отсеиваю через grep -v -e "test"

3. да вы правильно все поняли.


Сам файлик не могу выложить, там инфа с адресами и тд которую лучше не показывать.
Но вот такого формата файл
"ааа ""бббббббб""";ввввв;ул. яяяяяяя, 16;г Рррррр;100199101;100071552;0;10019900;10019900;лллллллл;557;30.06.2018;1;0;2.00;0.00;2.00;1;1;8;0;0
"ббб ""фффффффф""";ггггг;пр-т оооооо, 20;г Мммммм;100206101;700048682;0;10020600;10020600;кккккккк;3080;30.06.2018;2;0;2.00;0.00;2.00;1;3;2;0;0
"ааа ""бббббббб""";ввввв;ул. яяяяяяя, 16;г Рррррр;100199101;100071552;0;10019900;10019900;лллллллл;557;30.06.2018;1;0;2.00;0.00;2.00;1;1;8;0;0
"ббб ""фффффффф""";ггггг;пр-т оооооо, 20;г Мммммм;100206101;700048682;0;10020600;10020600;кккккккк;3080;30.06.2018;2;0;2.00;0.00;2.00;1;3;2;0;0
"ааа ""бббббббб""";ввввв;ул. яяяяяяя, 16;г Рррррр;100199101;100071552;0;10019900;10019900;лллллллл;557;30.06.2018;1;0;2.00;0.00;2.00;1;1;8;0;0
"ббб ""фффффффф""";ггггг;пр-т оооооо, 20;г Мммммм;100206101;700048682;0;10020600;10020600;кккккккк;3080;30.06.2018;2;0;2.00;0.00;2.00;1;3;2;0;0
"ааа ""бббббббб""";ввввв;ул. яяяяяяя, 16;г Рррррр;100199101;100071552;0;10019900;10019900;лллллллл;557;30.06.2018;1;0;2.00;0.00;2.00;1;1;8;0;0
"ббб ""фффффффф""";ггггг;пр-т оооооо, 20;г Мммммм;100206101;700048682;0;10020600;10020600;кккккккк;3080;30.06.2018;2;0;2.00;0.00;2.00;1;3;2;0;0
"ааа ""бббббббб""";ввввв;ул. яяяяяяя, 16;г Рррррр;100199101;100071552;0;10019900;10019900;лллллллл;557;30.06.2018;1;0;2.00;0.00;2.00;1;1;8;0;0
"ббб ""фффффффф""";ггггг;пр-т оооооо, 20;г Мммммм;100206101;700048682;0;10020600;10020600;кккккккк;3080;30.06.2018;2;0;2.00;0.00;2.00;1;3;2;0;0
"ааа ""бббббббб""";ввввв;ул. яяяяяяя, 16;г Рррррр;100199101;100071552;0;10019900;10019900;лллллллл;557;30.06.2018;1;0;2.00;0.00;2.00;1;1;8;0;0
"ббб ""фффффффф""";ггггг;пр-т оооооо, 20;г Мммммм;100206101;700048682;0;10020600;10020600;кккккккк;3080;30.06.2018;2;0;2.00;0.00;2.00;1;3;2;0;0
"ааа ""бббббббб""";ввввв;ул. яяяяяяя, 16;г Рррррр;100199101;100071552;0;10019900;10019900;лллллллл;557;30.06.2018;1;0;2.00;0.00;2.00;1;1;8;0;0
"ббб ""фффффффф""";ггггг;пр-т оооооо, 20;г Мммммм;100206101;700048682;0;10020600;10020600;кккккккк;3080;30.06.2018;2;0;2.00;0.00;2.00;1;3;2;0;0

Оффлайн inkblack

  • Старожил
  • *
  • Сообщений: 1216
    • Просмотр профиля
Есть очень хорошая книжка:
Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger — «The AWK programming language».
Рекомендую. Язык несложный вполне.

Код: Bash
  1. awk -F";" '
  2. #   Правильно будет работать при условии ...
  3.    { num[$8] = $8; sum[$8] += $17 }
  4. END { for (res in num) print num[res], sum[res] }' infile

В качестве самостоятельного упражнения сами избавьтесь от   -F";",   от   grep -v "test"   и попробуйте понять, при каком условии будет правильно работать.

(Вижу, вы приложили заметные усилия, а результат был не очень. Я думаю, что сто́ит постараться в правильном направлении)

(Нажмите, чтобы показать/скрыть)
Делюсь знаниями, но их у меня мало!

Онлайн Azure

  • СуперМодератор
  • Старожил
  • *
  • Сообщений: 5510
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
inkblack, а зачем еще один массив (num)?{ sum[$8] += $17 }
END { for (res in sum) print res, sum[res] }
*интригу с test сохраняю, а по поводу -F сам не понял что Вы имели ввиду...
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн inkblack

  • Старожил
  • *
  • Сообщений: 1216
    • Просмотр профиля
Может быть, я неправильно что-то понял в   awk,   но:
sum[1]=10
sum[2]=20
for (res in sum) print res, sum[res]

— что напечатает?

У меня там и вправду есть ненужное усложнение, но не настолько. Завтра допишу, сейчас — спать.
Делюсь знаниями, но их у меня мало!

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 14345
  • Я не слышу.
    • Просмотр профиля
Цитировать
for x in `cat $TMPFILE2 | awk -F " " '{print$1}'`;

while read x
do
....
done < $TMPFILE2

Онлайн Azure

  • СуперМодератор
  • Старожил
  • *
  • Сообщений: 5510
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
что напечатает?
Самому сложно проверить?
Код: HTML
  1. awk 'BEGIN{sum[1]=10;sum[2]=20;for(res in sum)print res,sum[res]}'
  2. 1 10
  3. 2 20

Пользователь добавил сообщение 03 Июль 2018, 10:47:52:
В екселе тоже несложно, там есть функция   =СУММЕСЛИ()
Если мы заговорили про эксель, то через сводную таблицу задача решается намного проще суммирования по условию
« Последнее редактирование: 03 Июль 2018, 10:47:52 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн inkblack

  • Старожил
  • *
  • Сообщений: 1216
    • Просмотр профиля
...
Самому сложно проверить?
Код: HTML
  1. awk 'BEGIN{sum[1]=10;sum[2]=20;for(res in sum)print res,sum[res]}'
  2. 1 10
  3. 2 20

— с телефона ночью писал, вот и не проверил

Код: HTML
  1. 1 10
  2. 2 20
— Значит, я действительно неправильно понял этот момент в   awk.

а по поводу -F сам не понял что Вы имели ввиду...
Это не писать
Код: Bash
  1. awk -F ";" '# команды ...'
А просто
Код: Bash
  1. awk '# другие команды ...'
Делюсь знаниями, но их у меня мало!

Онлайн Azure

  • СуперМодератор
  • Старожил
  • *
  • Сообщений: 5510
  • elementaryOS 0.4 Loki, i3wm on Debian9
    • Просмотр профиля
А просто
Все равно не понял. Разделитель ведь так и есть точка с запятой...
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн fill.sa

  • Автор темы
  • Любитель
  • *
  • Сообщений: 77
    • Просмотр профиля
inkblack, а зачем еще один массив (num)?{ sum[$8] += $17 }
END { for (res in sum) print res, sum[res] }
*интригу с test сохраняю, а по поводу -F сам не понял что Вы имели ввиду...

Подправил только вывод накоце с табом между столбами , а так в остальном то что нужно. Правда пока плохо понимаю что тут происходит - нужно вникать.

Спасибо большое.

Пользователь добавил сообщение 06 Июль 2018, 19:53:31:
awk -F ";"

Это нужно, во входящем файле столбцы через ; разбиты же.

Оффлайн inkblack

  • Старожил
  • *
  • Сообщений: 1216
    • Просмотр профиля
Есть очень хорошая книжка:
Alfred V. Aho, Brian W. Kernighan, Peter J. Weinberger — «The AWK programming language».
Там всё есть.

Цитировать
awk -F ";"
— просто можно по-другому то же самое указать.
Делюсь знаниями, но их у меня мало!

 

Страница сгенерирована за 0.52 секунд. Запросов: 24.