Edite valores em um arquivo txt com o comando sed / awk / grep

9

Por 5 anos, eu uso uma estação meteorológica La Crosse WS2350. Os dados fornecidos pela estação meteorológica são processados com open2300 no RPI. Isso funciona muito bem. No entanto, os dados de temperatura são falsos (sensor). Os dados de temperatura são 1 ° C mais baixos.

Como não posso calibrar o sensor, quero alterar o valor de temperatura do arquivo extraído da estação meteorológica.

Este arquivo de texto (current.txt) contém:

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
...

Eu quero adicionar +1 aos valores "To", "Tomin", "Tomax" e sobrescrever o arquivo de texto com os valores corretos.

Depois de observar os comandos sed e awk, percebo que estou desatualizado. Alguém pode me guiar? Obrigado

Editar:

Esqueci outro arquivo: ws2308.log A cada 15 minutos, uma nova linha é adicionada ao arquivo 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 

O valor a ser modificado é o quinto campo (o primeiro -1.2)

Também é necessário que, na última linha, o valor da temperatura seja incrementado em 1 e sobrescreva a última linha com o valor correto. Apenas a última linha será levada em conta pelo programa php, que permite exibir os resultados em um gráfico.

Obrigado

    
por Ookpik 03.12.2016 / 11:09

5 respostas

12

Aqui está uma variante AWK um pouco mais idiomática para processar current.txt ( a segunda resposta de Steve é ainda mais idiomática! ):

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

Isso procura as linhas que começam com To , seguidas por nada, min ou max , seguidas por um espaço; para linhas correspondentes, o primeiro campo e o segundo campo são incrementados, separados pelo separador de campos de saída padrão (espaço). Então, ele pula para a próxima linha. Todas as outras linhas são impressas como estão ( 1 é um atalho para isso no AWK).

Observe que sobrescrever o arquivo com os novos valores provavelmente não é uma boa ideia: você não saberá se os valores foram corrigidos ou não ... Se você recuperar o arquivo do dispositivo toda vez, isso não acontece aplicar.

O mesmo raciocínio se aplica a ws2308.log , então vamos processá-lo inteiramente:

$ 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

Se você quiser apenas a última linha:

$ 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

ou se você quiser o arquivo com apenas a última linha alterada :

$ 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
    
por 03.12.2016 / 14:13
10

Aqui está uma solução. Para todas as linhas que começam com "To", "Tomin" ou "Tomax" seguidas por um espaço, imprima o primeiro campo e depois o segundo campo incrementado por 1. Caso contrário, basta imprimir a linha completa.

$ 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
$
    
por 03.12.2016 / 11:40
5

Outra abordagem, um pouco golfe .

$ 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
$
    
por 03.12.2016 / 16:03
5

Uma abordagem Perl:

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

O -i faz com que o arquivo original seja sobrescrito, para que não seja impresso nada, ele irá alterar o arquivo diretamente.

O -a faz com que perl aja como awk , dividindo sua entrada em whitesapce (ou qualquer outra coisa dada por -F ) na matriz @F . Portanto, o segundo campo será $F[1] porque as matrizes começam a contar em 0. O script substituirá o segundo campo por ele mesmo incrementado por um nas linhas que começam com To .

    
por 03.12.2016 / 18:52
2

Isso fará o trabalho:

  1. Primeiro, passará por todas as linhas
  2. Em seguida, verifique o primeiro item e verifique se ele corresponde ao que você deseja.
  3. Então, se corresponder, imprima e adicione +1 ao próximo item na linha
  4. Ou apenas imprima e imprima o próximo item

    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
    

OUTPUT

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
    
por 03.12.2016 / 11:40