答案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
您可以使用sed
的N
命令将多行读入模式空间。
查找第一个:
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
保持安静,直到我们要求输出 - 这与p
print 命令结合使用,以模仿grep
-r
使用扩展正则表达式/}/N
找到一行}
并将下一行读入模式空间/^[^}]*$/N
找到没有的行}
,并将下一行读入模式空间I
不区分大小写的搜索p
打印找到/编辑的行s/old/new
old
用。。。来代替new