我有一个包含这种格式记录的文件:
D20220327,S2927,977,1
D20220328,S2927,977,1
D20220329,S2927,977,1
D20220330,S2927,977,1
D20220331,S2927,977,1
D20220401,S2927,977,1
D20220402,S2927,977,1
D20220403,S2927,977,1
D20220404,S2927,977,1
但是,在应用转换以将这些转换为过去 7 天之后,它不适用于从 3 月 28 日到 4 月 3 日的日期,但是相同的代码逻辑在 3 月 27 日和 4 月 4 日可以正常工作。我无法弄清楚为什么这仅在一周内不起作用。这是输出
D20220320,S2927,977,1 -- correct
D20220320,S2927,977,1 -- incorrect
D20220321,S2927,977,1 -- incorrect
D20220322,S2927,977,1 -- incorrect
D20220323,S2927,977,1 -- incorrect
D20220324,S2927,977,1 -- incorrect
D20220325,S2927,977,1 -- incorrect
D20220326,S2927,977,1 -- incorrect
D20220328,S2927,977,1 -- correct
这里使用的逻辑是:
BEGIN {
OFS = FS = ","
}
{
t = mktime(sprintf("%4d %.2d %.2d 00 00 00",
substr($1,2,4),
substr($1,6,2),
substr($1,8,2)));
$1 = substr($1,1,1) strftime("%Y%m%d", t - 7*24*60*60)
print
}
您的计算是在当地时间完成的,您会受到 3 月 27 日切换到夏令时的影响。
要改为使用 UTC 时间进行计算(Unix 时间戳不是本地时间),请使用最新版本的 GNU
awk
,确保将额外的1
作为最后一个参数传递给mktime()
:这是GNU版本 4.2.0+
awk
中可用的 GNU 扩展。awk
作为替代方案,您可以避免使用午夜 (UTC) 附近的时间作为您一天中的参考时间:
这将使它在较旧的 GNU
awk
实现和任何其他awk
具有所需功能的实现中工作。另一种选择是使脚本以更改的本地时区运行:
这会将
TZ
环境变量设置UTC
为执行awk
脚本,这会改变mktime()
和相关函数使用的时区。使用 Raku(以前称为 Perl_6)
示例输入(删除空行):
样本输出:
简而言之,Raku 的 linewise(自动打印)
-pe
标志与熟悉的运算符一起使用s///
。数字被捕获到匹配变量$0
,$1
, 和$2
括号中,并且捕获标记<( … )>
用于删除匹配的所有其他元素。{ … }
在替换中,Raku 在块内执行代码。、和捕获使用适当的破折号 ( ) 进行字符串化$0
,并且此字符串被识别为对象,可以在该对象上调用方法。[注意:一些用户可能会发现写作是一种更熟悉的语法——任何一种形式都可以]。一旦对象返回 7 天,它的-ingified 并用于删除返回中的破折号 ( )。$1
$2
-
Date
earlier(:7days)
earlier(days => 7)
Date
Str
subst
-
https://docs.raku.org/routine/Date
https://docs.raku.org/routine/Dateish
https://raku.org