Редагуйте значення у файлі txt за допомогою команди sed / awk / grep


9

Протягом 5 років я використовую метеостанцію La Crosse WS2350. Дані, надані метеостанцією, обробляються open2300 на RPI. Це працює дуже добре. Однак дані про температуру помилкові (датчик). Дані про температуру на 1 ° С нижче.

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

Цей текстовий файл (current.txt) містить:

Date 2016-Dec-03
Time 10:30:29
Ti 11.9
Timin 11.6
Timax 27.7
TTin 10:34
DTimin 2016-01-19
TTimax 00:44
DTimax 2016-08-28
To -2.4
Tomin -4.8
Tomax 37.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
...

Я хочу додати +1 до значень "До", "Томін", "Томакс" і перезаписати текстовий файл правильними значеннями.

Переглянувши команди sed і awk, я розумію, що я застарів. Хтось може мене керувати? Дякую

Редагувати:

Я забув ще один файл: ws2308.log Кожні 15 хвилин у файл ws2308.log додається новий рядок:

...
20161203150600 2016-Dec-03 15:06:00 11.8 -1.1 -3.2 65 87 0.0 157.5 SSE -1.1 569.80 1015.700 
20161203152100 2016-Dec-03 15:21:00 12.3 -1.1 -3.2 64 87 0.0 157.5 SSE -1.1 569.80 1015.600 
20161203153600 2016-Dec-03 15:36:00 12.2 -1.2 -3.3 64 87 0.0 135.0 SE -1.2 569.80 1015.700 

Значення, яке потрібно змінити, - це 5-е поле (перше -1,2)

Також необхідно, щоб на останньому рядку значення температури збільшувались на 1 і перезаписували останній рядок з правильним значенням. Тільки останній рядок буде враховано програмою php, яка дозволяє відображати результати у графі.

Дякую

Відповіді:


12

Ось трохи більш ідіоматичний варіант AWK для обробки current.txt( друга відповідь Стіва є ще більш ідіоматичною!):

awk '/^To(|min|max) / { print $1, $2 + 1; next } 1' current.txt

Це шукає рядки, що починаються з To, а потім нічого min, або max, після чого пробіл; для відповідних рядків він друкує перше поле та друге поле, посилене, розділене роздільником вивідного поля за замовчуванням (пробілом). Потім він переходить до наступного рядка. Усі інші рядки друкуються як є ( 1є ярликом для цього в AWK).

Зауважте, що перезапис файлу з новими значеннями, мабуть, не є гарною ідеєю: ви не дізнаєтесь, чи були виправлені цінні значення чи ні ... Якщо ви завантажуєте файл із пристрою кожного разу, це не застосовується.

Це ж міркування стосується і цього ws2308.log, тому давайте просто опрацьовуємо його у всій повноті кожен раз:

$ awk 'NF >= 5 { $5 = $5 + 1 } 1' ws2308.log
20161203150600 2016-Dec-03 15:06:00 11.8 -0.1 -3.2 65 87 0.0 157.5 SSE -1.1 569.80 1015.700
20161203152100 2016-Dec-03 15:21:00 12.3 -0.1 -3.2 64 87 0.0 157.5 SSE -1.1 569.80 1015.600
20161203153600 2016-Dec-03 15:36:00 12.2 -0.2 -3.3 64 87 0.0 135.0 SE -1.2 569.80 1015.700

Якщо ви хочете лише останній рядок:

$ awk 'NF >= 5 { $5 = $5 + 1; lastline = $0 } END { print lastline }' ws2308.log
20161203153600 2016-Dec-03 15:36:00 12.2 -0.2 -3.3 64 87 0.0 135.0 SE -1.2 569.80 1015.700

або якщо ви хочете, щоб файл змінив лише останній рядок :

$ awk 'length(prevline) > 0 { print prevline } NF >= 5 { prevline = $0; $5 = $5 + 1; lastline = $0 } END { print lastline }' ws2308.log
20161203150600 2016-Dec-03 15:06:00 11.8 -1.1 -3.2 65 87 0.0 157.5 SSE -1.1 569.80 1015.700 
20161203152100 2016-Dec-03 15:21:00 12.3 -1.1 -3.2 64 87 0.0 157.5 SSE -1.1 569.80 1015.600 
20161203153600 2016-Dec-03 15:36:00 12.2 -0.2 -3.3 64 87 0.0 135.0 SE -1.2 569.80 1015.700

10

Ось одне рішення. Для будь-яких рядків, які починаються з «До», «Томін» або «Томакс», а потім пробіл, надрукуйте перше поле, а потім друге поле, збільшене на 1. В іншому випадку просто надрукуйте повний рядок.

$ awk '{if(/^(To|Tomin|Tomax) /){print $1 " " $2+1}else{print $0}}' w.txt
Date 2016-Dec-03
Time 10:30:29
Ti 11.9
Timin 11.6
Timax 27.7
TTin 10:34
DTimin 2016-01-19
TTimax 00:44
DTimax 2016-08-28
To -1.4
Tomin -3.8
Tomax 38.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
$

5

Ще один підхід, трохи гольф .

$ awk '/^To/{$2++}1' w.txt
Date 2016-Dec-03
Time 10:30:29
Ti 11.9
Timin 11.6
Timax 27.7
TTin 10:34
DTimin 2016-01-19
TTimax 00:44
DTimax 2016-08-28
To -1.4
Tomin -3.8
Tomax 38.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
$

3
Приємно (так +1), але ви могли просто додати це як редагування до існуючої відповіді!
Стівен Кітт

@Scott -iна awkдодає інклюднік, це нічого , як sed«S -iваріант.
Стівен Кітт

@StephenKitt: D'oh! Я знаю це.
Скотт

5

Підхід Perl:

perl -i -ape '/^To/ && s/$F[1]/$F[1]+1/e' file

-iРобить його перезаписує вихідний файл, тому він не буде друкувати нічого, це змінить файл безпосередньо.

В -aмарці perlдіє як awk, розщеплення його на вхід whitesapce (або що - небудь ще , даний -F) в масив @F. Отже, друге поле буде $F[1]тому, що масиви починають рахувати з 0. Сценарій, таким чином, замінить друге поле на себе, збільшене на одне у рядках, починаючи з To.


2

Це зробить роботу:

  1. Спочатку пройдемо всі лінії
  2. Потім перевірте перший предмет і перевірте, чи відповідає він бажаному.
  3. Потім, якщо він збігається, роздрукуйте його та додайте +1 до наступного пункту рядка
  4. Ще просто роздрукуйте його та надрукуйте наступний елемент

    awk '{
        for(i=1;i<=NF;i++) {
                t+=$i;if(i==1){
                        if($i=="To" ||$i=="Tomin" ||$i=="Tomax"  ){
                                printf  "%s ",$i;
                                print $(i+1)+1;}
    
                        else{
                                print $0
                                }
                        }
                        };
        }' current.txt
    

ВИХІД

Date 2016-Dec-03
Time 10:30:29
Ti 11.9
Timin 11.6
Timax 27.7
TTin 10:34
DTimin 2016-01-19
TTimax 00:44
DTimax 2016-08-28
To -1.4
Tomin -3.8
Tomax 38.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.