我有一个 MySQL 转储文件,其中大部分是 INSERT 语句。我想从特定表的字段中 grep 出字符串“media”的实例,并包含 +/- ~10 个上下文字符。该字符串可能会在列的值中出现多次。我怎样才能做到这一点?
源是一个非常大的 sql 转储文件(为了简洁起见,我必须严格截断):
INSERT...334,'field_media_intro_image','image','image'...);
INSERT...g__vieg__view_mode__media_original attr__format....ategies that are immediately actionable for the task...);
我想看看
ield_media_intr
ode__media_orig, re immediately
其中上面的第一行是第一个匹配行中字符串“media”的一个实例,第二行显示下一个匹配行中字符串“media”的两个实例。两者都在字符串的开头和结尾处显示五个上下文字符。逗号充当分隔符。
答案1
GNU grep可以通过行获取上下文(-A LINES
对于上下文后,-B LINES
对于上下文前,并且-C LINES
对于语境之前和之后),但它没有水平上下文的标志。不过,您可以使用正则表达式来做到这一点:
grep -Eo '.{0,10}media.{0,10}'
(-E
使用扩展正则表达式(ERE),允许类似的语法.{0,10}
(匹配任何字符 0-10 次)。 GNU grep 的-o
显示仅有的匹配的内容,每行匹配一次。)
贪婪
请注意,这不会是一个完整的列表,因为“媒体”一词的某些副本可能与已捕获的内容太接近。例如:
$ echo 123 media 12345 media 123456789 media 12 |grep -Eo '.{0,10}media.{0,10}'
123 media 12345 med
234567890 media 123
你得到部分“media”的所有三个实例,但由于其中一个实例与另一个实例的部分距离在十个字符之内,因此仅显示了该实例的该部分。
如果有 GNU grep 编译库,你可以告诉这些通配符是懒惰而不是贪婪:
$ echo 123 media 12345 media 123456789 media 12 |grep -Po '.{0,10}?media.{0,10}?'
123 media
12345 media
234567890 media
该-P
标志使能Perl 兼容的正则表达式(PCRE)评估。
惰性求值(也称为“非贪婪求值”)旨在防止一个匹配干扰另一个匹配,而不是消耗尽可能多的十个字符,这限制了进一步的匹配。
如果您的版本grep
不支持-P
或-o
,您可以使用perl
:
$ echo 123 media 123 media 123456789 media 12 |perl -ne \
'while (/(.{0,10}?media.{0,10}?)/g) { print "$1\n"; }'
123 media
12345 media
234567890 media
这会稍微修改正则表达式以包含匹配组,以便我们稍后可以引用匹配的文本。否则,它只是每次匹配的循环(g
全局匹配而不是第一次匹配),然后用换行符打印匹配。
GNU 与 POSIX grep
GNU grep在上面添加了很多功能POSIX 标准 grep。具体到这个答案,-A LINES
(上下文行A之后),-B LINES
(上下文行乙之前),-C LINES
(行Context 之前和之后), -o
(显示哦仅匹配)和-P
(使用磷CRE)在 GNU grep 中都可用,但不能假定用于其他 grep 实现。 BSD grep支持除 之外的所有这些-P
,但 BSD 用户通常更喜欢 GNU grep,因为GNU 的性能优化。
GNU 和 BSDgrep
命令也都支持--color
,您可以将其用作-o
.这最终将显示带有颜色的匹配文本(“媒体”及其 0-10 个上下文字符)的整行。
最后一点:对该问题的评论使用了语法.{,5}
,该语法在grep -E
但几乎在其他地方都不起作用(当然也不grep -P
是perl
)。使用该格式而不是在 中明确包含零是一个坏习惯.{0,5}
。