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

9

Durante 5 anos, uso uma estação meteorológica La Crosse WS2350. Os dados fornecidos pela estação meteorológica são processados ​​com o 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 consigo calibrar o sensor, quero alterar o valor da 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
...

Quero adicionar +1 aos valores "Para", "Tomin", "Tomax" e substituir o arquivo de texto pelos valores corretos.

Depois de olhar para 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 5º campo (o primeiro -1,2)

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

obrigado

Ookpik
fonte

Respostas:

12

Aqui está uma variante AWK um pouco mais idiomática do processo 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 por linhas começando com To, seguidas por nada min, ou maxseguidas por um espaço; para linhas correspondentes, imprime o primeiro campo e o segundo campo, incrementado, separado pelo separador de campo de saída padrão (espaço). Em seguida, 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 substituir o arquivo pelos 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 todas as vezes, isso não se aplica.

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

$ 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ê deseja 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 que o arquivo com apenas a última linha seja alterado :

$ 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
Stephen Kitt
fonte
10

Aqui está uma solução. Para todas as linhas que começam com "Para", "Tomin" ou "Tomax" seguidas de um espaço, imprima o primeiro campo e, em seguida, o segundo campo incrementado por 1. Caso contrário, imprima 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
$
Steve
fonte
5

Outra abordagem, um pouco de 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
$
Steve
fonte
3
Bom (mais ou menos um), mas você poderia ter adicionado isso como uma edição à sua resposta existente!
Stephen Kitt
O @Scott -ion awkadiciona um arquivo de inclusão, não é nada parecido com seda -iopção.
Stephen Kitt
@StephenKitt: D'oh! Eu sabia.
Scott
5

Uma abordagem Perl:

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

O -itorna substituir o arquivo original, por isso vai imprimir nada, ele vai mudar o arquivo diretamente.

O -amakes perlage 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. Portanto, o script substituirá o segundo campo incrementado por um nas linhas que começam com To.

terdon
fonte
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. Em seguida, se corresponder, imprima-o e adicione +1 ao próximo item da linha
  4. Caso contrário, basta imprimi-lo e imprimir 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
    

RESULTADO

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
Wissam Roujoulah
fonte