Unix 脚本通过将数据与相同的关键记录进行比较来处理数据

Unix 脚本通过将数据与相同的关键记录进行比较来处理数据

我遇到的问题是输入文件具有有效日期和结束日期记录。前 6 个字段是键 (12345A)。我们需要根据具有相同键的下一条记录的有效(8 个位置)日期 - 1 天来更新结束日期(18 个位置)。对于生效日期最新的记录,结束日期应保留 9999-12-31。以下是输入和输出期望。有人可以帮我吗?我正在获取文件 A 作为表卸载,并且必须稍后将其发送到接口应用程序,该应用程序预计结束日期将像这样填充,我们无法更改表本身的结束日期,这就是我们尝试在卸载时更改它的原因文件。

没有数据分隔符/定界符,并且键的长度将始终保持不变。

输入(文件):

12345A22021-01-259999-12-31
12345A12021-01-019999-12-31
12345B32021-02-159999-12-31
67899C12021-03-019999-12-31
67899D32021-05-249999-12-31
67899D22021-04-029999-12-31

输出(文件B):

12345A22021-01-259999-12-31
12345A12021-01-012021-01-24
12345B32021-02-159999-12-31
67899C12021-03-019999-12-31
67899D32021-05-249999-12-31
67899D22021-04-022021-05-23

答案1

只要将具有相同ID的前一条记录的有效日期作为结束日期,就可以使用标准sedN;P;D模式来做到这一点,如下所示:

sed '$!N;s/^\(.\{6\}\)\(.\)\(.\{10\}\)\(.*\n\1.\{11\}\).*/\1\2\3\4\3/;P;D'

但是一旦您需要更改日期,您就需要一个能够理解日历的实用程序,例如 GNU date

date -d "2021-09-08 yesterday" +"%Y-%m-%d"

将输出2021-09-07.我怀疑许多版本都date会这样做。但对于当前的 GNUdate和 GNU sed,这应该可以工作:

sed -nE 'G
  s/^(.{6})(.{11}).*\n\1.(.{10}).*/\1\2\3/p
  s/\n.*//p
  s/^(.{7})(.{10})/echo \1$(date -d "\2 yesterday" +"%Y-%m-%d")/e
  h' fileA > fileB

让我尝试解释一下:

  • 我们使用选项n来抑制默认输出和E扩展正则表达式的选项(只是为了可读性)
  • G附加保留空间,我们将在其中保留上一行并加上适当的日期(见下文)
  • s/^(.{6})(.{11}).*\n\1.(.{10})/\1\2\3/p将当前行的日期替换为保留空间中的改编日期,前提是它具有相同的 ID(因此是反向引用\1)并p打印它
  • s/\n.*//p如果没有发生替换,则简单地删除附加行并p打印它
  • s/^(.{7})(.{10})/echo \1$(date -d "\2 yesterday" +"%Y-%m-%d")/e利用 GNUsedexecute 标志将日期发送到date实用程序以减少它
  • h保存此更改的行以保留空间

相关内容