输入
Time Value Flag
06:15:10 49.95 Actual
00:00:00 0.00 NoValue
06:22:50 49.94 Actual
06:23:00 49.93 Actual
06:23:10 49.93 Actual
06:23:20 49.93 Actual
06:23:30 49.93 Actual
06:24:40 49.92 Actual
00:00:00 0.00 NoValue
我必须替换包含“NoValue”的行。时间将替换为最后记录的时间,增量为 10 秒 (10 秒) 值将替换为最后记录的时间 标志将替换为实际值
我的结果将显示为,
Time Value Flag
06:15:10 49.95 Actual
06:15:20 49.95 Actual
06:22:50 49.94 Actual
06:23:00 49.93 Actual
06:23:10 49.93 Actual
06:23:20 49.93 Actual
06:23:30 49.93 Actual
06:24:40 49.92 Actual
06:24:50 49.92 Actual
答案1
awk -F'[: ]+' -v addSec=10 '
NR>1 && /Actual/{
sec=(($1*3600)+($2*60)+$3) +addSec;
prevTime=sprintf("%02d:%02d:%02d", sec/3600, sec%3600/60, sec%60) OFS $4 OFS $5;
}
/NoValue/{ $0=prevTime }1
' infile
答案2
尝试这个:
猫诺瓦| tr-s“”| awk -F"[:]" -f val.awk
在哪里:
cat noval
06:15:10 49.95 Actual
00:00:00 0.00
06:22:50 49.94 Actual
06:23:00 49.93 Actual
06:23:10 49.93 Actual
06:23:20 49.93 Actual
06:23:30 49.93 Actual
06:24:40 49.92 Actual
00:00:00 0.00
和
cat val.awk
{
if($5=="") {
print g
}
else {
print $0
$3=$3+10
if ($3>59){
$3=$3-60
$2=$2+1
}
if ($2>59){
$2=$2-60
$1=$1+1
}
if(length($1)<2) {$1="0"$1}
if(length($2)<2) {$2="0"$2}
if(length($3)<2) {$3="0"$3}
g=$1":"$2":"$3" "$4" "$5
}
}
结果是:
06:15:10 49.95 Actual
06:15:20 49.95 Actual
06:22:50 49.94 Actual
06:23:00 49.93 Actual
06:23:10 49.93 Actual
06:23:20 49.93 Actual
06:23:30 49.93 Actual
06:24:40 49.92 Actual
06:24:50 49.92 Actual
注意:使用 awk,我们沿着字符冒号 (:) 和空格分解每一行。这样我们就可以访问时间戳的三个组成部分(第 1、2、3 列),以便可能加 10。我们使用 tr 将多个空格压缩为一个。 awk 中的 F 标志被设置为沿着冒号和/或空格分解行以进行操作。
答案3
如果不知道时间戳适用的日期和时区,并且使用理解日期和时间的实用程序(即不仅仅是简单的数学),则无法通过在现有时间上添加 10 秒来确定新时间,因为新时间是以下结果的结果在给定时间上添加 10 秒会受到夏令时和闰秒的影响。
假设您输入时间戳的开始日期是今天,然后使用 GNU awk 来处理时间函数(它处理 DST,但与处理 POSIX 纪元时间的所有工具一样,不处理闰秒,所以希望您不关心这一点) ):
$ cat tst.awk
BEGIN {
OFS = " "
prevDate = (date=="" ? strftime("%Y %m %d") : date)
}
NR == 1 {
print
next
}
$3 == "NoValue" {
prevTime = gensub(/:/," ","g",prevLine[1])
prevSecs = mktime(prevDate " " prevTime)
currSecs = prevSecs + 10
prevDate = strftime("%Y %m %d",currSecs)
$1 = strftime("%T",currSecs)
$2 = prevLine[2]
$3 = prevLine[3]
}
{
print
split($0,prevLine)
}
$ awk -f tst.awk file
Time Value Flag
06:15:10 49.95 Actual
06:15:20 49.95 Actual
06:22:50 49.94 Actual
06:23:00 49.93 Actual
06:23:10 49.93 Actual
06:23:20 49.93 Actual
06:23:30 49.93 Actual
06:24:40 49.92 Actual
06:24:50 49.92 Actual
如果您希望在计算机设置的时区之外的其他时区应用时间计算,请在执行上述操作之前适当设置 shell 变量,或者在对和TZ
的调用上设置 UTC 标志,请参阅mktime()
strftime()
https://www.gnu.org/software/gawk/manual/gawk.html#Time-Functions。
如果您想使用与今天不同的开始日期,请调用脚本以awk -v date='2021 10 03' -f tst.awk file
提供您喜欢的YYYY MM DD
格式的任何日期。
上面假设时间戳将始终填充在输入的第二行中,因为您没有说明如何处理它。
请注意,正如 @PhilipCouling 在评论(或任何其他库)中指出的那样,mktime()
仅给出日期和时间无法可靠地返回自纪元以来的秒数,对于在 DST 结束时的转换间隔期间具有 DST 的时区(DST 开始时很好) )。他们提供的例子是:
在英国,日期/时间 2022 年 10 月 30 日上午 01:30:00 将发生两次。这是因为,当时钟到达凌晨 2 点时,DST 将结束,时钟会向后跳一小时至凌晨 1 点。因此,1:30 在 DST 结束之前发生一次,在 DST 结束之后发生一次。该文件不包含有关它描述的这两者中哪一个的任何信息。该文件不会告诉您 DST 是否已结束。
答案4
使用乐(以前称为 Perl_6)
~$ raku -e 'my @init = [Z=>] lines[0].words, (DateTime.new("2024-01-01T00:00:00Z"), "0.00", "Initial");
put @init.map(*.key).join("\t");
for lines.map(*.words) -> ($t,$v,$f) {
if $f eq "NoValue" {
put join "\t", @init[0].value.hh-mm-ss, @init[1..*].map(*.value) andthen
@init[0] = @init[0].key => @init[0].value.later(:10seconds);
} else {
put join "\t", ($t,$v,$f) andthen
@init = [Z=>]
@init.map(*.key),
(DateTime.new("2024-01-01T" ~ $t ~ "Z").later(:10seconds),$v,$f)
}
};' file.txt
Raku 是 Perl 系列中的一种编程语言,具有DateTime
内置 ISO 8601 对象。上面我们将初始行 ( line[0]
) 作为标头读取,并使用初始值(包括初始时间戳)创建键/值对DateTime
。归约元运算符[Z=>]
采用其后面的两个列表,并将它们“压缩”在一起作为键/值对,并将其分配给数组@init
(即对数组)。这会立即输出put
(在\t
选项卡上连接),以重建标题行。
从这里我们迭代lines
.每行都被映射并分解为words
(即列),这些行被分配给临时$t,$v,$f
变量以在块内使用:
- 如果
$f
标志字符串等于“NoValue” ,则输出eq
其中的值。@init
然后我们增加时间戳。 - 如果
$f
标志ne
字符串不等于“NoValue”,则($t,$v,$f)
输出该行的值,并@init
使用这些新值更新数组($t,$v,$f)
,这些新值将替换默认/旧值。然后时间戳会递增。
Raku 的一个优点是,DateTime
此类函数later(:10seconds)
可用于在时间戳上添加 10 秒,以便在下一个“NoValue”标记行中进行插补。还hh-mm-ss
允许您仅返回时间部分(请注意,我们使用任意日期2024-01-01
,因为这最终会被丢弃)。
示例输入(OP 的示例输入,NoValue
末尾有额外的行):
Time Value Flag
06:15:10 49.95 Actual
00:00:00 0.00 NoValue
06:22:50 49.94 Actual
06:23:00 49.93 Actual
06:23:10 49.93 Actual
06:23:20 49.93 Actual
06:23:30 49.93 Actual
06:24:40 49.92 Actual
00:00:00 0.00 NoValue
00:00:00 0.00 NoValue
示例输出 1(来自上面):
Time Value Flag
06:15:10 49.95 Actual
06:15:20 49.95 Actual
06:22:50 49.94 Actual
06:23:00 49.93 Actual
06:23:10 49.93 Actual
06:23:20 49.93 Actual
06:23:30 49.93 Actual
06:24:40 49.92 Actual
06:24:50 49.92 Actual
06:25:00 49.92 Actual
[上面的注释:样本输入末尾的多个连续“NoValue”行的时间戳正确递增]。
测试“NoValue”初始数据行:为了确定,下面我们可以删除第一个 ( Actual
) 数据行,使其00:00:00 0.00 NoValue
成为第一个数据行。
示例输出 2(来自上面的示例输入,减去第一个/Actual
数据行):
Time Value Flag
00:00:00 0.00 Initial
06:22:50 49.94 Actual
06:23:00 49.93 Actual
06:23:10 49.93 Actual
06:23:20 49.93 Actual
06:23:30 49.93 Actual
06:24:40 49.92 Actual
06:24:50 49.92 Actual
06:25:00 49.92 Actual
以上处理正确并报告Initial
已估算(人工)值。
https://www.iso.org/iso-8601-date-and-time-format.html
https://docs.raku.org/type/DateTime
https://raku.org