根据可能位于特定列中任何位置的日期过滤文件

Posted

技术标签:

【中文标题】根据可能位于特定列中任何位置的日期过滤文件【英文标题】:Filter file on dates that could be anywhere in a particular column 【发布时间】:2022-01-24 01:43:00 【问题描述】:

假设我有一个包含两列的文件:

blahblah2020-02-03_moreblah | VALUE |
blah2021-03-04blah | VALUE |

使用 awk 我只需要选择第一列中的日期小于我拥有的其他日期的那些行。烦人的事情是日期可能在任何一方的任何奇怪的字符串中,或​​者根本没有 - 但它的格式是 YYYY-mm-dd。我不确定我是如何最终陷入不得不使用 awk 的情况,但我在这里,我非常感谢您!

【问题讨论】:

请更新问题以显示日期在第 2 列中的一些数据(根据您的评论 '可能在任一侧的任何奇怪字符串中'),代码您已经尝试过代码生成的(错误)输出 对不起,让我澄清一下,日期总是在第一列。第二列无关紧要 - 我只是将其包括在内以使数据看起来更像一个表格。 至于我已经尝试过的,我仍在努力将日期添加到新列中。 【参考方案1】:

假设:

日期将始终采用YYYY-MM-DD 格式(在 OP 的描述中确认) 任何感兴趣的日期将仅位于第一个 |-delimited 字段中 第一个字段最多只能包含一个日期字符串(即不必担心第一个字段包含多个日期字符串)

使用GNU awk 4.0(或更新版本)支持FPAT

awk -v testdt="$dt" '                                        # pass bash variable "dt" in as awk variable "testdt"
BEGIN  FPAT="[12][0-9]3-[012][0-9]-[0123][0-9]"             # define pattern we are looking for; if exists it should be field #1
#       FPAT="[[:digit:]]4-[[:digit:]]2-[[:digit:]]2"    # one of a few alternatives
      

$1 < testdt                                                    # if we have a match for FPAT and less than testdt then echo entire line to stdout
' input.dat

注意:如果输入可能包含格式为 ####-##-## 且不是有效日期的数据,则 OP 可能需要调整 FPAT 定义和/或添加更多逻辑来验证在运行测试之前匹配为实际日期 ($1 &lt; testdt)

这里使用 OP 的 2 行示例输入是使用 (bash) 变量 dt 的不同值的一些结果:

$ dt='2019-06-01'
$ awk -v testdt="$dt" 'BEGIN FPAT="[12][0-9]3-[012][0-9]-[0123][0-9]" $1 < testdt' input.dat
       -- no output --

$ dt='2020-06-01'
$ awk -v testdt="$dt" 'BEGIN FPAT="[12][0-9]3-[012][0-9]-[0123][0-9]" $1 < testdt' input.dat
blahblah2020-02-03_moreblah | VALUE |

$ dt='2021-06-01'
$ awk -v testdt="$dt" 'BEGIN FPAT="[12][0-9]3-[012][0-9]-[0123][0-9]" $1 < testdt' input.dat
blahblah2020-02-03_moreblah | VALUE |
blah2021-03-04blah | VALUE |

【讨论】:

如果我从我发布的数据中创建一个 input.dat 文件,那么对于您使用的三个日期中的每一个,此代码都不会为我返回任何内容。我很困惑这怎么会发生,因为你显然已经让它工作了?编辑:看起来我已经 mawk 1.3.4 而不是我需要的新 awk。 @CClarke 请查看更新后的答案;我实际上替换了 3 个点(认为有人可能不明白这是答案前面列出的完整 awk 脚本的快捷方式【参考方案2】:

在任何 shell 中,在每个 Unix 机器上使用任何 awk:

$ awk -v tgt='2020-05-01' 'match($0,/[0-9]4(-[0-9]2)2/) && (substr($0,RSTART,RLENGTH) < tgt)' file
blahblah2020-02-03_moreblah | VALUE |

$ awk -v tgt='2021-05-01' 'match($0,/[0-9]4(-[0-9]2)2/) && (substr($0,RSTART,RLENGTH) < tgt)' file
blahblah2020-02-03_moreblah | VALUE |
blah2021-03-04blah | VALUE |

【讨论】:

【参考方案3】:

\d\d\d\d-\d\d-\d\d https://regexone.com/ 它有效,但有更好的解决方案 如果您希望它少于通常使用此正则表达式语法在 pyhton 中编写脚本,方法是收集所有日期,然后根据之前的位置进行过滤 - 无论是大于还是小于您拥有的日期。 对于我在日期范围内: if date[i]

【讨论】:

正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。 没有强制性的 POSIX 工具,也没有可以理解该正则表达式的 awk 版本。只有工具非常适合生成/验证在该在线工具中工作的正则表达式,但它们对于在命令行工具中运行正则表达式的用处是微不足道的。

以上是关于根据可能位于特定列中任何位置的日期过滤文件的主要内容,如果未能解决你的问题,请参考以下文章

PHP,Codeigniter:如何在Web应用程序中根据用户时区/位置设置日期/时间?

Pandas:根据字符串的一部分是不是在另一列中的任何位置创建新列

如何获取位于 JFrame 中特定布局位置的组件

回收站视图滚动到特定位置

如何使用awk根据数值范围向列添加特定值

SQL - 根据另一列中的日期过滤一列的结果