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

Ook*_*pik 9 sed text-processing

5 年来,我使用气象站 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
...
Run Code Online (Sandbox Code Playgroud)

我想将 +1 添加到值“To”、“Tomin”、“Tomax”并用正确的值覆盖文本文件。

查看 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 
Run Code Online (Sandbox Code Playgroud)

要修改的值是第5个字段(第一个-1.2)

还需要在最后一行将温度值加 1,并用正确的值覆盖最后一行。php 程序只考虑最后一行,它允许在图表中显示结果。

谢谢

Ste*_*itt 12

这是一个稍微更惯用的 AWK 变体来处理current.txt史蒂夫的第二个答案更加惯用!):

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

这将查找以 开头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
Run Code Online (Sandbox Code Playgroud)

如果你只想要最后一行:

$ 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
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望只更改最后一行的文件:

$ 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
Run Code Online (Sandbox Code Playgroud)


ste*_*eve 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
$
Run Code Online (Sandbox Code Playgroud)


ste*_*eve 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
$
Run Code Online (Sandbox Code Playgroud)

  • 很好(所以+1),但您可以将其添加为对现有答案的编辑! (3认同)

ter*_*don 5

Perl 方法:

perl -i -ape '/^To/ && s/$F[1]/$F[1]+1/e' file
Run Code Online (Sandbox Code Playgroud)

-i使它覆盖原始文件,因此它不会打印任何内容,它会直接更改文件。

-a品牌perlawk,分裂其对whitesapce输入(或任何其他由给定-F)到阵列@F。因此,第二个字段将是$F[1]因为数组从 0 开始计数。因此,脚本将替换第二个字段,使其在以 开头的行上增加 1 To