【问题标题】:How to search for a pattern inside a file and delete the lines in Unix on the command line?如何在文件中搜索模式并在命令行中删除 Unix 中的行?
【发布时间】:2010-11-28 04:29:16
【问题描述】:

我需要在文件中搜索模式。 例如文件内容如下:

3555005!K!00630000078!C!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
3555005!D!16042296!DUMMY!20090805235959!0!47001231000000!0!336344324!1!1!POST!USAGE!336344324!0!
3555005!C!336344324!1!!!EUR!1!1!!I!
3555005!S!00630000078!20090805172515!LF010300!

我想在这里搜索带有 !D! 的行并且该行中的第 7 个字段小于系统日期,那么我想删除该行并保存文件。

这可能吗?

【问题讨论】:

  • 请将示例数据格式化为代码块,您可以通过编辑问题、选择文本并按 CTRLK跨度>

标签: unix sed awk grep


【解决方案1】:

这样的事情应该可以解决问题...如果这不是您设置字段格式的方式,您可能需要解析时间

perl -ne '/^([^!]+!){6}([^!]+).*/; print if $2 < time && /!D!/;'

【讨论】:

    【解决方案2】:

    如果您更喜欢 AWK...

    awk -f logstrip.awk  in.log > out.log
    

    logstrip.awk 看起来像

    # *** Simple AWK script to delete lines from log file ***
    #    Rule: keep all lines except these that have their 2nd
    #          field equal to "D" and their 7th field more than
    #          current date time
    
    
    BEGIN {
        FS = "!";   #delimiter
    
        stopDate = systime();
        # stopDate = 47001231000001;   for test purposes
    
        deletedLineCtr = 0;   #diagnostics counter, unused at this time
    }
    
    {
      if (match($2, "D") && ($7 < stopDate) ) {
        deletedLineCtr++;
      }
      else
         print $0
    }
    

    应该可以解决问题。

    但是请注意,您的字段 #7 包含奇怪的日期格式。我想我认识一个最近的纪元值(123 ...),但它前面有 4 个明显不相关的数字。在与 StopDate 进行比较之前,这些可以很容易地删除

    【讨论】:

    • 可能是第五个字段。顺便说一句,不要打印“zz”和 $0,只需颠倒测试的逻辑,只打印(不)匹配的行。
    • Thks,Dennis W,这个“zz”的东西是我在发布之前忘记清理的一些测试时间代码......我清理了这个,而不是逆转测试(但那很好想法,因为我们没有用 deletedLineCtr 做任何有用的事情)!
    【解决方案3】:

    基于 mjv 的 答案,但简化并使用(假设)日期的第五个字段(为了便于阅读,分为两行):

    awk -F! 'BEGIN {stopdate=strftime("%Y%m%d%H%M%S",systime())} 
             $2 != "D" || $5 >= stopdate {print}' file.log > newfile.log
    

    【讨论】:

    • "print $0" 是多余的——只需“print”即可。事实上,如果这是 awk 程序中的最后一个动作,您可以完全省略该动作,因为它是默认动作:awk -F! -v date=$(date '+%Y%m%d%H%M%S') '$2 != "D" || $5 >= 日期'
    • 你是对的。但是,我会留下 print 以避免过多的混淆。
    【解决方案4】:

    我用文件中的样本数据进行了测试

    3555005!K!00630000078!C!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!D!16042296!DUMMY!20090805235959!0!20090912000000!0!336344324!1!1!POST!vijay!336344324!0!
    3555005!C!336344324!1!!!EUR!1!1!!I!
    3555005!S!00630000078!20090805172515!LF010300!
    3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!D!16042296!DUMMY!20090805235959!0!20090912000000!0!336344324!1!1!POST!vijay!336344324!0!
    3555005!C!336344324!1!!!EUR!1!1!!I!
    3555005!S!00630000078!20090805172515!LF010300!
    3555005!D!16042296!DUMMY!20090805235959!0!20090917000000!0!336344324!1!1!POST!USAGE!336344324!0!
    3555005!C!336344324!1!!!EUR!1!1!!I!
    3555005!S!00630000078!20090805172515!LF010300!
    3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!D!16042296!DUMMY!20090805235959!0!20090919000000!0!336344324!1!1!POST!USAGE!336344324!0!
    3555005!C!336344324!1!!!EUR!1!1!!I!
    3555005!S!00630000078!20090805172515!LF010300!
    3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!D!16042296!DUMMY!20090805235959!0!20090914000000!0!336344324!1!1!POST!vijay!336344324!0!
    3555005!C!336344324!1!!!EUR!1!1!!I!
    3555005!S!00630000078!20090805172515!LF010300!
    3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!D!16042296!DUMMY!20090805235959!0!20090915000000!0!336344324!1!1!POST!vijay!336344324!0!
    3555005!C!336344324!1!!!EUR!1!1!!I!
    3555005!S!00630000078!20090805172515!LF010300!
    3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!D!16042296!DUMMY!20090805235959!0!20090913000000!0!336344324!1!1!POST!vijay!336344324!0!
    3555005!C!336344324!1!!!EUR!1!1!!I!
    3555005!S!00630000078!20090805172515!LF010300!
    3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!D!16042296!DUMMY!20090805235959!0!20090912000000!0!336344324!1!1!POST!USAGE!336344324!0!
    3555005!C!336344324!1!!!EUR!1!1!!I!
    3555005!S!00630000078!20090805172515!LF010300!
    3555005!K!204042880166840!I!20090805235959!47001231000000!16042296!336344324!A!1!ENG!0!00630000078!NO!00630000078!
    3555005!D!16042296!DUMMY!20090805235959!0!20090912000000!0!336344324!1!1!POST!USAGE!336344324!0!
    

    但它正在删除由 !D! 组成的所有行。 我使用了以下 awk 脚本

    # *** Simple AWK script to delete lines from log file ***
    #    Rule: keep all lines except these that have their 2nd
    #    field equal to "D" and their 7th field more than
    #          current date time
    BEGIN {
           FS = "!";
             #delimiter
             stopDate = "date +%Y%m%d%H%M%S";
             # stopDate = 47001231000001;  for test purposes
             deletedLineCtr = 0;   #diagnostics counter, unused at this time
          }
          {
          if ( match($2, "D") && ($7 < stopDate) )
              {
               deletedLineCtr++;
              }
          else
               print $0
          }
    

    我做错了什么吗?

    【讨论】:

    • 请使用代码和块引用功能格式化您的帖子,以便它们可读。 awk 没有这样的“日期”命令。另外,我不认为“47001231000001”是一个日期(除非你去掉“4700”,否则它看起来像是自纪元以来的秒数)。在您的第一篇文章中,该值在字段 7 中,但字段 5 看起来像一个日期。在这篇文章中,该值位于某些记录的字段 6 中,但字段 7 看起来像一个日期。请参阅我的答案或 mjv 的。如果选择了正确的字段,任何一个都应该工作。继续尝试。你快到了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 2012-09-27
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    • 2015-08-31
    • 2015-11-10
    相关资源
    最近更新 更多