Grep一个日志文件,表示两个字符串之间最后一次出现的字符串

时间:2013-10-30 11:59:30

标签: unix grep tail

我有一个日志文件trace.log。在其中我需要grep查找字符串<tag></tag>中包含的内容。这对字符串有多组,我只需要在最后一组(换句话说,来自日志文件的tail)之间返回内容。

额外信用:只有当内容包含“testString”时,我才能返回两个字符串中包含的内容?

感谢您的光临。

编辑:搜索参数和包含在不同的行上,大约有100行内容将它们分开。内容就是我追求的......

5 个答案:

答案 0 :(得分:33)

使用tac以相反的方式打印文件,然后使用grep -m1打印一个结果。背后的外观和前瞻检查<tag></tag>之间的文本。

tac a | grep -m1 -oP '(?<=tag>).*(?=</tag>)'

测试

鉴于此文件

$ cat a
<tag> and </tag>
aaa <tag> and <b> other things </tag>
adsaad <tag>and  last one</tag>

$ tac a | grep -m1 -oP '(?<=tag>).*(?=</tag>)'
and  last one

更新

  

编辑:搜索参数和包含在不同的行上   大约有100行内容将它们分开。内容就是我的意思   之后...

然后它有点棘手:

tac file | awk '/<\/tag>/ {p=1; split($0, a, "</tag>"); $0=a[1]};
                /<tag>/   {p=0; split($0, a, "<tag>");  $0=a[2]; print; exit};
                p' | tac

我们的想法是撤消文件并使用标记p来检查<tag>是否已经出现。它将在</tag>出现时开始打印,并在<tag>到来时结束(因为我们正在相反地阅读)。

  • split($0, a, "</tag>"); $0=a[1];获取</tag>
  • 之前的数据
  • split($0, a, "<tag>" ); $0=a[2];获取<tag>
  • 之后的数据

测试

给出这样的文件a

<tag> and </tag>
aaa <tag> and <b> other thing
come here
and here </tag>

some text<tag>tag is starting here
blabla
and ends here</tag>

输出将是:

$ tac a | awk '/<\/tag>/ {p=1; split($0, a, "</tag>"); $0=a[1]}; /<tag>/ {p=0; split($0, a, "<tag>"); $0=a[2]; print; exit}; p' | tac
tag is starting here
blabla
and ends here

答案 1 :(得分:22)

如果像我一样,你无法访问tac,因为你的系统管理员不会打球,你可以试试:

grep pattern file | tail -1

答案 2 :(得分:1)

除了grep之外的另一个解决方案是sed:

tac file | sed -n '0,/<tag>\(.*\)<\/tag>/s//\1/p'

tac file以相反的顺序打印文件(cat向后),然后sed从输入行0继续到<tag>.*<\tag>的第一次出现,并将<tag>.*<\tag>仅替换为<tag>内的部分。 p标志打印输出,该输出被-n抑制。

修改:如果<tag></tag>位于不同的行,则无效。我们仍然可以使用sed

tac file | sed -n '/<\/tag>/,$p; /<tag>/q' | sed 's/.*<tag>//; s/<\/tag>.*//' | tac

我们再次使用tac向后读取文件,然后第一个sed命令从第一次出现时读取,并在找到时退出。仅打印中间的行。然后我们将它传递给另一个sed进程以剥离它们,最后用tac再次反转这些行。

答案 3 :(得分:0)

perl -e '$/=undef; $f=<>; push @a,$1 while($f=~m#<tag>(.*?)</tag>#msg); print $a[-1]' ex.txt
  

额外信用:任何方式我都可以返回其中包含的内容   仅当内容包含“testString”时才有两个字符串?

perl -e '$/=undef; $f=<>; push @a,$1 while($f=~m#<tag>(.*?)</tag>#msg); print $a[-1] if ($a[-1]~=/teststring/);' ex.txt

答案 4 :(得分:0)

一个处理多行的未经测试的 awk:

awk '
    BEGIN    {retain="false"}
    /<\tag>/ {retain = retain + $0; keep="false"; next}
    /<tag>/  {keep = "true"; retain = $0; next}
    keep == "true" {retain = retain + $0}
    END {print retain}
' filename

我们开始阅读文件;当我们点击时,我们开始保持线条。当我们击中时,我们停下来。如果我们击中另一个,我们清除保留的字符串并重新开始。如果您想要所有字符串,请在每个

打印