sed 命令:bash 中的正则表达式以排除某些字符串

sed command: regex in bash to exclude certain strings

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

数据:

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" 来排除开头的日期。这有效。

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

尝试:

$ 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 将始终从行首开始匹配。

只需使用 awk:

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

  • sub(/^ */,"",[=13=]) - 删除行首的过多空格

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

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

我会使用这样的东西:

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

哪里

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

测试

$ 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

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

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

它搜索具有 match 的(给定种类的)日期(我们不都是 :) 和带括号的字符串以及它们周围的 substrs。