使用sed / awk / grep命令编辑txt文件中的值


9

五年来,我使用气象站La Crosse WS2350。气象站提供的数据在RPI上使用open2300处理。这很好。但是,温度数据是错误的(传感器)。温度数据低1°C。

由于无法校准传感器,因此我想更改从气象站提取的文件中的温度值。

此文本文件(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
...

我想为值“ To”,“ Tomin”,“ Tomax”添加+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仅考虑最后一行,该程序允许在图形中显示结果。

谢谢

Answers:


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

这是一个解决方案。对于以“ To”,“ Tomin”或“ Tomax”开头,后跟一个空格的任何行,请打印第一个字段,然后将第二个字段递增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 -ion awk添加了一个包含文件,它与sed-i选项完全不同。
史蒂芬·基特

@StephenKitt:天哪!我知道。
斯科特

5

Perl方法:

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

-i使得其覆盖原文件,因此它会打印出什么,这将直接改变文件。

-a品牌perlawk,分裂其对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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.