检查文件中的字符串是否与正则表达式匹配,如果不匹配则打印出该行中的第一个字符串

Wic*_*man -1 grep macos

首先,我是新手,所以我仍在学习..

数据集文件有点像这样

101 80 10 27598 General Tao Vancouver 01:45:10 01:46:10 00:43:00 00:59:59 01:25:10
Run Code Online (Sandbox Code Playgroud)

我正在尝试检查时间以确保它们与 的格式匹配/d/d:/d/d:/d/d,如果它与该正则表达式不匹配,则它会打印出该行的第一个数字(在这种情况下为 101)

我一直在 CLI 中尝试一种衬垫,但无济于事。

grep '/d/d:/d/d:/d/d' file.txt
Run Code Online (Sandbox Code Playgroud)

即使为此也没有任何反应

edit1:在数据集中,有些数据看起来像 01:4510 或类似的

我希望得到的示例输出是:

104 80 10 27598 BigBelly Vancouver 01:4510 01:46:10 00:43:00 00:59:59 01:25:10
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 5

您一定一直在考虑匹配十进制数字的正则\d表达式运算符perl。但请注意,很少有grep实现支持它。标准等价物是[[:digit:]]

一些grep实现支持\dif 传递一个-P选项(使用类似 perl 的正则表达式而不是基本的正则表达式)。

所以有了这些,你可以这样做:

grep -Pv '\d\d:\d\d:\d\d' < file.txt
Run Code Online (Sandbox Code Playgroud)

返回不包含与该模式匹配的字符串的行。

(请注意,它们是反斜杠而不是正斜杠

或者:

grep -Pv '(\s+\d\d:\d\d:\d\d){5}\s*$' < file.txt
Run Code Online (Sandbox Code Playgroud)

对于不以 5 个这样的时间戳结尾的行。

要在这种情况下返回第一个字段,您可以改为grep执行(使用也支持 的实现-o

grep -Po '^(?!.*(\s+\d\d:\d\d:\d\d){5}\s*$)\s*\K\S+' < file.txt
Run Code Online (Sandbox Code Playgroud)

这次使用否定前瞻 perl 正则表达式运算符而不是使用grep's -v

grepMACOS(你说你正在使用,现在我已经删除的从你的问题的标签,取而代之的是),恰好是那几个,其基本的正则表达式支持一个\d,但它不支持-P,那么那些(?!...)\K运营商不可有。

一个标准(更清晰)的等价物是:

awk '!/([[:digit:]]{2}:){2}[[:digit:]]{2}/ {print $1}' < file.txt
Run Code Online (Sandbox Code Playgroud)

awk使用扩展的正则表达式,这是另一种方言。当心一些实现,包括mawk仍然不支持{2}间隔运算符或字符类。

在 中mawk,你会这样做:

awk '!/[0-9][0-9]:[0-9][0-9]:[0-9][0-9]/ {print $1}' < file.txt
Run Code Online (Sandbox Code Playgroud)

这也应该适用于其他awk实现,但请注意,对于某些[0-9]可能会匹配 0123456789 以外的字符(非 ASCII 字符,因此您的输入可能不是问题)。

或者再次检查所有 5 个最后的字段是否与模式匹配:

awk '
  {
    for (i = 0; i < 5; i++)
      if (!($(NF-i) ~ /^[0-9][0-9]:[0-9][0-9]:[0-9][0-9]$/)) {
        print $1
        next
      }
  }' < file.txt
Run Code Online (Sandbox Code Playgroud)

  • @Wickerman,您添加的那一行确实包含一些有效的 HH:MM:SS,因此不会被报告。如果我们要检查*所有*时间戳是否有效,那么我们需要知道这些时间戳应该在哪里找到。例如,在您的第一个示例中,第 7 个字段包含不是有效时间戳的“Vancouver”。时间戳是否总是每行的最后 5 个字段?你在什么操作系统上? (2认同)