Как обработать таблицу в bash?
Есть команда которая генерирует таблицу из трех колонок Status, Owner, Value. В столбце Status - текстовые значения, в стоблце Owner - текстовое значение может быть с пробелом, в колонке value - целочисленные, но могут быть пустые (вместо 0). Например:
#gentbl
Status Owner Value
active Alpha A. 101
active Betta 5
active Alpha A.
error Alpha A. 2
active Betta 359
Требуется подсчитать сумму значений по каждому владельцу в статусе active.
Пробовал разбирать по строкам через цикл for, но разбор идет не по строкам, а словам, причем из-за особенностей стоблбцов Owner и Value способ очень сложен.
for line in $(gentbl)
do
...
done
Заранее спасибо
Bash работа с таблицами
faddist88, реализация на bash критична? Если нет, пробуйте Python + библиотеку Numpy.
Очень желательно именно на bash, т.к. решение типовое, а python'a может не быть
Очень желательно именно на bash, т.к. решение типовое, а python'a может не быть
bash не совсем для этого предназначен.
т.е. в нём нет встроенных средств для генерации таблиц.
напишите утилиту, на вашем любимом языке программирования.
[quote="faddist88"]Очень желательно именно на bash, т.к. решение типовое, а python'a может не быть
bash не совсем для этого предназначен.
т.е. в нём нет встроенных средств для генерации таблиц.
напишите утилиту, на вашем любимом языке программирования.[/quote]
Понятно что bash не очень подходит - день гугления до создания темы мне это подсказало, но очень хочется реализовать именно на bash, чтобы работало всегда вне зависимости от установленных библиотек и т.д. Понимаю что это попытка совершуть кругосветное путешествие на мопеде: очень сложно, но в целом можно. Только подскажите как выделять в переменную целую строку из вывода. Как разбирать строку мне уже более менее понятно.
чтобы работало всегда вне зависимости от установленных библиотек
Вариант с компиляцией в двоичный код не подходит?
как выделять в переменную целую строку из вывода
написать парсер.
искать символ CR во вводе.
или использовать функцию языка типа как cin >> a или readln(a);
[quote="faddist88"]чтобы работало всегда вне зависимости от установленных библиотек
Вариант с компиляцией в двоичный код не подходит?[/quote]
Можно ссылку с примером чтобы было понятно как это сделать. Это можно будет потом таскать между серверами на разных ОС и железе?
Добавлено: 26.04.2022 10:34:40
[quote="faddist88"] как выделять в переменную целую строку из вывода
написать парсер.
искать символ CR во вводе.
или использовать функцию языка типа как cin >> a или readln(a);[/quote]
Опять же можно пример или ссылку
Опять же можно пример или ссылку
создать массив строк
ввести текст
в цикле пока не закончится строка
искать разделитель строки
добавить строку в массив строк
дальше
[quote="faddist88"]Опять же можно пример или ссылку
создать массив строк
ввести текст
в цикле пока не закончится строка
искать разделитель строки
добавить строку в массив строк
дальше[/quote]
Алгоритм понятен. Я даже пробовал конструкции типа
for line in $(gentbl)
do
парсим строку $line
done
Но в этом случае в $line записываются не строки целиком, а слова или символы разделенные пробелами.
Если использовать такую конструкцию
result=$(gentbl)
То в каждой строке своя ячейка, но там где ячейки пустые там нет пустой строки
Добавлено: 26.04.2022 11:35:59
Как распарсить строку я более-менее понимаю. Проблема именно в способе перебора строк вывода результата
Можно ссылку с примером чтобы было понятно как это сделать. Это можно будет потом таскать между серверами на разных ОС и железе?
От железа зависеть практически не будет, а вот под Linux/Windows надо будет отдельно компилировать.
А ссылку - вопрос слишком абстрактный, записит от того, на каком языке писать.
for line in $(gentbl)
do
парсим строку $line
done
Но в этом случае в $line записываются не строки целиком, а слова или символы разделенные пробелами.
парсить в цикле по строкам по разделителю CR
парсить в цикле по строкам по разделителю пробелу
обрабатывать табличное значение
дальше
дальше
Как обработать таблицу в bash?
Здравствуйте. В каждой таблице, если это именно таблица, а не набор строк, должен присутствовать разделитель полей/столбцов. Если его нет - значит это обычный текст, который так же бесполезно разбивать на столбцы/поля, как искать иголку в стоге сена. Если нет разделителя - мы читаем обычную страницу из любой книги и неважно, что соседние ячейки соответствуют определённому формату: содержит она пробел или не содержит, стоит там точка или не стоит, похожа она на ту, что сверху/снизу или нет. Без разделителя вся эта писанина, называемая таблицей - обычный набор текста, который ничем не структурирован.
Предположим, что Ваша программа gentbl всё же сгенерировала Вашу таблицу как таблицу и разделителем полей является табуляция (TAB). Тогда Ваша задача может быть решена старым дедовским способом, например через промежуточные файлы (их будет не менее 4-х):
Скрипт ./start.sh
#!/bin/bash
#Если разделитель полей - табуляция, то...
#Нормализация исходной таблицы ./table: убираем заголовок, заменяем все пробелы на '_',
#выделяем статус 'active' и сохраняем всё это добро в файл ./table_normalized
cat ./table | tr ' ' '_' | tail -n+2 | grep 'active' > ./table_normalized
#Список уникальных имён сохраняем в файл ./owners
cat ./table_normalized | cut -f2 | sort | uniq > ./owners
#Сохраняем список сумм для каждого пользователя в файлы ./sum_ИмяПользователя
while read p; do
cat table_normalized | grep "$p" | cut -f3 | grep -v '_' > "sum_$p"
done < ./owners
#Подсчет суммы для каждого owner-а из их собственных файлов ./sum_ИмяПользователя
for i in $(ls ./sum_*); do
#Обнуляем счётчик сумм
result=0
while read p; do
let result=result+"$p"
done < $i
echo "Сумма для $(echo $i | cut -c 7-): $result"
done
read -p "Enter - выйти..."
Результат работы:
> ./start.sh
Сумма для Alpha_A.: 101
Сумма для Betta: 364
Enter - выйти...
alex_q_2000, да тут проще можно сделать.
1. Считываем строку.
2. Если первые 6 символов образуют слово "active" (для надёжности приведём к нижнему регистру), переходим к шагу 3, иначе возврат на шаг 1.
3. Считываем из конца строки по одному символу, если это цифры. Если нет - имеем ноль. Прибавляем полученное значение к сумме.
4. Пока не достигнут конец файла, переход к шагу 1.
Кстати, цифры в конце строки можно вырезать регулярным выражением: /(\d*)$/gi, дальше пусть автор темы сам подумает. Если в конце цифр нет, это выражение вернёт пустую строку.
Ну или сразу для полного анализа строки: /active .+ (\d*)$/gi (обратите внимание на пробелы в выражении, они там нужны!).