我把输入作为11列文件;分隔。
ARM5914447;2023-10-17 18:05:38;2023-10-19 16:11:29;Missing name;Reassigned; Release;Mark;.com;p4;Vail;.com
ARM5914448;2023-10-18 19:05:38;2023-10-19 16:11:29;Missing name;Reassigned; Release;Tony;.com;p4;Vail;.com
字符串
我需要比较第二列的日期与今天的日期和打印在同一文件中的第12列的天数差值。
我想出了这个awk命令
awk -F";" 'NR == 1 { print $0";difference of days"; next } { "date -d \"today\" +%s" | getline today; "date -d \""$2"\" +%s" | getline filedate; diff = int((today - filedate) / 86400); print $0";"diff }'
型
当只是打印diff时,它看起来很好,但是打印$0”;“diff,它没有附加第12列,我在这里缺少了什么
2条答案
按热度按时间dldeef671#
当我运行你的脚本时,我得到以下输出:
字符串
请注意,新数据被追加到行的末尾。
如果我将文件转换为包含windows/dos行结尾(
\r\n
),新数据将在行的开头结束,例如:型
请注意,新数据显示在该行的前面。
在这一点上,我想知道如果你的脚本是打印新的数据在行的开头,你碰巧错过了它。
你可以通过几种方式来检查windows/dos的行尾,例如:
型
一个简单的修复方法是从文件中删除
\r
字符(例如,运行dos2unix
),然后运行awk
脚本,例如:型
另一个让
awk
从每行中删除尾随的\r
的选项:型
7nbnzgx92#
正如其他人所指出的,你几乎肯定会有DOS行结尾,参见Why does my tool output overwrite itself and how do I fix it?,这可以通过在awk脚本的开头输入
{sub(/\r$/,"")}
来解决。除此之外,
awk
调用Unix命令时,它都必须生成一个子shell来执行该命令,这是非常慢的,如果可能的话最好避免。考虑到这一点,如果你不能避免调用date
,那么你应该将"date -d \"today\" +%s" | getline today
移动到BEGIN
部分,这样它就必须在每行输入中少生成一个子shell,这样脚本的运行速度就快了一倍。date
,在你生成它们之后,所以YMMV会处理一个大的输入文件,因为你可能会超过一个进程允许的最大打开“文件”数量。它可能会失败,出现“打开文件太多”错误(大多数awk),或者当它试图在内部管理打开/关闭文件时(GNU awk),速度会明显变慢。getline
的方式是不安全的,因为失败会悄悄地破坏您的输出,而不会被检测到(请参阅http://awk.freeshell.org/AllAboutGetline)。diff = int((today - filedate) / 86400)
不会告诉你两个日期之间的天数,它会告诉你两个日期之间的86400秒间隔,向下舍入。所以,如果文件中的时间是昨天的12:01 pm,而你在今天的12:01 pm运行脚本,那么它会告诉你两天之间有0天,而不是期望的1天,假设你确实需要计算日期之间的天数差。如果你有或者可以安装GNU awk,它有自己的内置时间函数,然后你可以使用这个脚本来解决上述所有问题:
字符串
型
我假设这是预期的产出,因为今天是2023年11月3日,并且:
型
它与输入中的
$2
中的日期匹配。请注意,我仍然在计算秒,但我正在计算输入日期的中午与今天日期的中午之间的差异(而不是使用当前时间和输入时间)然后除以一天中的秒数,结果总是两个日期之间的天数。该计算依赖于POSIX定义的一天中始终有86400秒Unix时间
除了生成准确的输出之外,上面的脚本运行速度将比现有脚本快几个数量级,因为它不生成任何子shell。
如果你没有GNU awk,那么将你的脚本改为:
型
型
这也将解决您的所有问题,除了与GNU awk版本相比,它仍然非常慢,除非您在输入中只有少数几个唯一的日期。它的运行速度将是原始脚本的两倍多,因为它在每行输入中生成一个子shell,其中包含以前看不到的日期(因为我们在
Date_Secs[]
中缓存日期到秒的Map),而不是在每个输入行生成2个子shell。