当我在一行中搜索模式时,怎样才能包含上面一行中的信息?

当我在一行中搜索模式时,怎样才能包含上面一行中的信息?

使用 grep 检索信息时,我需要区分第一幅图像和第二幅图像的情况。它们都是 created_at,但一个用于图像,一个用于推文。所有用于推文的都},在上面的行中,所以我想我可以使用该信息,但我不确定如何做到这一点。

这是我使用的 grep:

grep -wirnE 'Wed Oct 19 2(1:[0-5][0-9]:[0-5][0-9]|2:([0-2][0-9]:[0-5][0-9]|30:00)) .* 2016' *

在此处输入图片描述

在此处输入图片描述

答案1

您可以使用选项-A1-B1打印grep匹配行之后(-A)和之前(-B)的行。尝试以下命令行,

grep -B1 created_at log-file|grep -A1 '^}'|grep created_at

我使用以下输入文件进行了测试log-file

asdf
qwerty
...
},
"created_at" "date-with-near-}"
zxcv
some other string
"created_at" "date-without-}"
...

测试顺序

$ grep -B1 created_at log-file
},
"created_at" "date-with-near-}"
--
some other string
"created_at" "date-without-}"

$ grep -B1 created_at log-file|grep -A1 '^}'
},
"created_at" "date-with-near-}"

$ grep -B1 created_at log-file|grep -A1 '^}'|grep created_at
"created_at" "date-with-near-}"

答案2

您可以使用sedN命令将多行读入模式空间。

查找第一个:

sed -nr '/\}/N; /.*\}.*\n.*"Wed Oct 19 .* 2016/Ip' file

并删除前一行:

sed -nr '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' file

问题是它sed不会告诉你该行来自哪个文件,并且它没有递归文件搜索标志(据我所知)。可以通过**在 shell 中打开递归通配符来解决此问题(但“该行来自哪个文件?”问题仍然存在):

shopt -s globstar
sed -nrs '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' **

对于多个文件,添加-s标志使sed流被视为单独的文件(以避免不必要的多行匹配)您可以在中间添加详细的表达......

sed -nrs '/}/N; s/.*}.*\n(.*"Wed Oct 19 2(1:[0-5][0-9]:[0-5][0-9]|2:([0-2][0-9]:[0-5][0-9]|30:00)) .* 2016)/\1/Ip' **

对于第二次出现且}前一行没有

sed -nr '/^[^}]*$/N; /.*\n.*"Wed Oct 19 .* 2016/Ip' file

并删除前一行:

sed -nr '/^[^}]*$/N; s/.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' file

将其组合成更有用的东西:

for f in **; do [[ -f "$f" ]] && echo -e ""$f":\n tweet: $(sed -nr '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' "$f")\n image: $(sed -nr '/^[^}]*$/N; s/.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' "$f")"; done 

或者...稍微更易读一些(!)

#!/bin/bash
shopt -s globstar

for f in **; do 
   [[ -f "$f" ]] && 
   echo -e ""$f":\n tweet: $(sed -nr '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' "$f")"
done 

输出如下:

file1:
 tweet: "created_at": "Wed Oct 19 12:36:54 +0000 2016"
 image: "created_at": "Wed Oct 19 somethingsomething 2016"
file2:
 tweet: "created_at": "Wed Oct 19 random-chars 2016"
 image: "created_at": "Wed Oct 19 whatever 2016"

如果您想排除其中一个,请从脚本中删除相关部分,例如仅获取推文...

for f in **; do 
   [[ -f "$f" ]] && 
   echo -e ""$f":\n tweet: $(sed -nr '/}/N; s/.*}.*\n(.*"Wed Oct 19 .* 2016)/\1/Ip' "$f")"
done

笔记

  • sed -n保持安静,直到我们要求输出 - 这与pprint 命令结合使用,以模仿grep
  • -r使用扩展正则表达式
  • /}/N找到一行}并将下一行读入模式空间
  • /^[^}]*$/N找到没有的行},并将下一行读入模式空间
  • I不区分大小写的搜索
  • p打印找到/编辑的行
  • s/old/newold用。。。来代替new

相关内容