【问题标题】:sed command: regex in bash to exclude certain stringssed 命令:bash 中的正则表达式以排除某些字符串
【发布时间】:2017-09-06 07:04:01
【问题描述】:

我想排除剪辑和日期中的所有内容,但选择所有其他数据。

数据:

02.04.2001 ERROR (User1) Server can't start
01.02.2005 ERROR (User2) Server can't start
07.08.2006 ERROR (User1) Problem with Login
12.05.2009 ERROR (User2) Problem with Login

期望的输出:

ERROR  Server can't start
ERROR  Server can't start
ERROR  Problem with Login
ERROR  Problem with Login

我尝试了类似sed -n "s/^.*ERROR/ERROR/p" 的方法来排除开头的日期。这行得通。

我不知道如何排除“(用户)”字符串。

【问题讨论】:

  • 如果我使用它,它会显示除与正则表达式匹配的数据之外的所有内容

标签: regex linux bash shell regex-negation


【解决方案1】:

试试:

$ sed -n "s/[^)]*ERROR ([^)]*)/ERROR/p" file
ERROR Server can't start
ERROR Server can't start
ERROR Problem with Login
ERROR Problem with Login

我们添加了捕获用户字符串的正则表达式([^)]*)

为了防止字符串ERROR 在一行中出现多次,我们将ERROR 之前的正则表达式从.* 更改为[^)]*。这可以防止正则表达式匹配任何可能出现在(User1) 字符串之后的ERROR 字符串。

请注意,前导 ^ 是不必要的。 Sed 的正则表达式匹配最左边最长的匹配。这意味着.*ERROR 将始终从行首开始匹配。

【讨论】:

  • 似乎是正确的解决方案,但我仍然遇到一些问题。如果该行有更多字符串,例如“02.04.2001 ERROR [unknown area] (User1) Server can't start”,您的正则表达式是否仍然有效?
  • @J.Doe 要检测和删除ERROR(User1) 之间的字符,请尝试:sed -n "s/.*ERROR[^)]*([^)]*)/ERROR/p" file。这会在 ERROR 和用户之间添加 [^)]*' to match any number of non-)` 字符。
  • @J.Doe 想象像12.05.2009 ERROR (User2) Problem (aa(bb)cc)dd with (ee) ff) Login这样的一行
  • @RuslanOsmanov 当前代码可以很好地处理该行,因为正则表达式 [)]*) 将匹配第一个,而不是最后一个紧随其后的括号。如果一行中出现多个ERROR 字符串,则可能会出现问题;我已经更新了解决这个问题的答案。
  • @John1024,嗯,真的吗?我以为this不是他想要的
【解决方案2】:

只需 awk

awk '{ $1=$3=""; sub(/^ */,"",$0) }1' file
  • $1=$3="" - 清除第一个和第三个字段

  • sub(/^ */,"",$0) - 删除行首多余的空格

输出(因为您想要的输出在第 1 项和第 2 项之间有 2 间隔分隔符):

ERROR  Server can't start
ERROR  Server can't start
ERROR  Problem with Login
ERROR  Problem with Login

【讨论】:

    【解决方案3】:

    我会使用这样的东西:

    sed -E 's/^\S+\s+//; s/\(\S+\)//g; s/\s\s*/ /g' file
    

    在哪里

    • -E 选项启用ERE syntax;
    • s/^\S+\s+// 删除后跟一个或多个空白字符(即日期和其后的空格)的非空白字符;
    • s/\(\S+\)//g 删除括号中的序列;
    • s/\s\s*/ /g 用一个空格替换重复的空格。

    测试

    $ cat sample 
    02.04.2001 ERROR (User1) Server can't start
    01.02.2005 ERROR (User2) Server can't start
    07.08.2006 ERROR (User1) Problem with Login
    12.05.2009 ERROR (User2) Problem with Login
    12.05.2009 ERROR (User2) Problem (sfsdfsdf(sdfsdf)sdfsf) with (another) aaa) Login
    12.05.2009 ERROR (User2) Problem with asdfsdf(sadfasdf) Login
    12.05.2009 ERROR (User2) Problem (sfsdfsdf(sdfsdf)sdfsf)aa with (another) aaa) Login
    
    $ sed -E 's/^\S+\s+//; s/\(\S+\)//g; s/\s\s*/ /g' sample
    ERROR Server can't start
    ERROR Server can't start
    ERROR Problem with Login
    ERROR Problem with Login
    ERROR Problem with aaa) Login
    ERROR Problem with asdfsdf Login
    ERROR Problem aa with aaa) Login
    

    使用 Perl 几乎相同:

    perl -pe 's/^\S+\s+//; s/\(\S+\)//g; s/\s{2,}/ /g' file
    

    【讨论】:

      【解决方案4】:

      在 awk 中。 gsub 会更容易,但我有使用 match 的意义,但我忘记了(:

      $ awk '
      {
          while(match($0,/(^| )(([0-9]{2}\.){2}[0-9]{4}|\([^)]*\))($| )/))
              $0=(RSTART==1?"":substr($0,1,RSTART)) substr($0,RSTART+RLENGTH)
      }1' file
      ERROR Server can't start
      ERROR Server can't start
      ERROR Problem with Login
      ERROR Problem with Login
      

      它使用match(不是我们所有人:)搜索(给定的)日期,并在它们周围加上括号字符串和substrs。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-28
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多