Автор Тема: выделение части текста в bash  (Прочитано 6725 раз)

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

Vena

  • Собеседник
  • ****
  • Сообщений: 375
    • Просмотр профиля
выделение части текста в bash
« : Пятница, 15 Мая, 2015, 10:39:33 »
Имею текст
Using pin #21
Data (40): 0x1f 0x0 0x19 0x0 0x38
Temp = 25 *C, Hum = 31 %
Это данные перенаправленные с датчика влажности и температуры.
Как создать 2 разных файла, в первом значение температуры, во втором влажности? Что-то не знаю :(

vovka

  • Global Moderator
  • Про
  • *****
  • Сообщений: 787
    • Просмотр профиля
    • www.nixzeya.ru.net
Re: выделение части текста в bash
« Ответ #1 : Пятница, 15 Мая, 2015, 15:23:07 »
Как один из вариантов, можно применить текстовый процессор awk для расчленения текста. Например:

echo "Temp = 25 *C, Hum = 31 %" | grep "Temp" | awk '{print$3}' >> file-temp.txt
echo "Temp = 25 *C, Hum = 31 %" | grep "Temp" | awk '{print$7}' >> file-hum.txt
Комбинация:
echo "Temp = 25 *C, Hum = 31 %"
- это эмуляция вывода программы, которая выводит результат.
Сам процесс детально:
| grep "Temp"  - из вывода выделяем именно строку с параметрами по наличию Temp и перенаправляем дальше:
| awk '{print$3}' - здесь awk отделяет из всего ввода третье слово с начала строки (параметр print$3) и выводит только его в файл, причём дописывая (оператор ">>" ) новые значения в новую строку:
>> file-temp.txt

Вторая строка примера отличается только выводом 7-го слова.
Важно! Нужно учесть, как будут отображаться отрицательные температуры - или это будет целое слово, например -25, или с пробелом: - 25 . В первом случае алгоритм отработает корректно, во втором - минус посчитается за отдельное слово.

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

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

Если в итоге нужен лог, то не имеет смысла просто сохранять массив данных без привязки ко времени  - надо добавлять текущее время, применив команду date с опциями формата вывода.

Например, как будет выглядеть однопроходный процесс с записью в разные логи:
Предположим вывод сохраняется в /tmp/result.txt

#!/bin/bash

# Задаём переменные, указывающие на файлы

RESULT_FILE="/tmp/result.txt"     # путь до файла, куда записывается вывод
SUMMARY_LOG="/tmp/summary.log"    # путь до полного лога
TEMP_LOG="/tmp/temperature.log"   # путь до лога температуры
HUM_LOG="/tmp/humidity.log"       # путь до лога влажности

# Проверки
test -r $RESULT_FILE || exit 0  # Если файла нет или он нечитаем  - ничего не делаем, просто завершить работу
test -r $SUMMARY_LOG || touch $SUMMARY_LOG  # Если файла нет или он нечитаем - создаём его.
test -r $TEMP_LOG || touch $TEMP_LOG        # Если файла нет или он нечитаем - создаём его.
test -r $HUM_LOG || touch $HUM_LOG          # Если файла нет или он нечитаем - создаём его.


# Разбор текста и сохранение текста в переменные
TEMPER=`cat $RESULT_FILE | grep "Temp" | awk '{print$3}'`
HUMID=`cat $RESULT_FILE | grep "Temp" | awk '{print$7}'`

# Создание временной метки про формат - смотреть man date
TIMESTAMP=`date +"%F %R"`

# Вывод
echo "$TIMESTAMP $TEMPER $HUMID" >> summary.log
echo "$TIMESTAMP $TEMPER" >> temperature.log
echo "$TIMESTAMP $HUMID" >> humidity.log

exit 0

Лог summary.log - опциональный, в нём содержится оба значения за раз:


cat summary.log
2015-05-15 20:51 24 31
2015-05-15 20:54 22 33
2015-05-15 20:54 21 31

- это самая простейшая текстовая база данных. Если немного уложнить, можно и MySQL прикрутить с дальнейшей обработкой и постройкой графиков. Кстати, я поторопился и записались два значения с одним временем - 20:54. Одно дело, если сбор данных будет идти раз в пять минут, а другое - стохастично. В этом случае в формат штампа времени нужно ввести секунды и даже миллисекунды. Всё есть в man date.

Небольшое пояснение, зачем нужны проверки. Первая проверка логична - если файла нет, то и выполнять дальнейшие вещи не имеет смысла. Со второй по четвёртую смысл таков - вывод результата производится не командой замещения - >, а дополнения - >> . Встречались случаи, когда дополнение не работает в несуществующий файл. Так, если файл ещё не создан, просто выводится ошибка. Без этой проверки bash в Ubuntu 14.04 выполняет создание нового файла и добавляет в него данные, но лучше проверить.

test -r $HUM_LOG - выполняется проверка, существует ли файл и есть ли у скрипта, в котором выполняется команда, права на чтение этого файла. Выдаёт "0", если истинно.

|| - операция логического ИЛИ

Если в левой части "1", то выполняется команда touch $HUM_LOG

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

Очень рекомендую книжку Mendel Cooper "Advanced Bash-Scripting Guide" в переводе Алексея Кисилёва - в ней описано множество примеров программирования на bash. Есть в оксовской библиотечке.

Примерно так.
« Последнее редактирование: Пятница, 15 Мая, 2015, 15:40:29 от vovka »
*nix - свобода мысли, свобода творчества!

Vena

  • Собеседник
  • ****
  • Сообщений: 375
    • Просмотр профиля
Re: выделение части текста в bash
« Ответ #2 : Пятница, 15 Мая, 2015, 17:33:56 »
Спасибо. Сделал пока через awk
/home/pi/sources/./readDHT 11 21 >/home/pi/temperature/tmp.txt
cat /home/pi/temperature/tmp.txt | grep "Temp" | awk '{print$3}' > /home/pi/temperature/file-temp.txt
cat /home/pi/temperature/tmp.txt | grep "Temp" | awk '{print$7}' > /home/pi/temperature/file-hum.txt
а дальше в базу rrdtol
Пока так, потом оптимизирую. Нужно пособирать статистику работы датчика, часты ли всплески "левых" значений. Будет график изменений.