从文件中查找字符串的多个实例以及上下文

从文件中查找字符串的多个实例以及上下文

我有一个 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 -Pperl)。使用该格式而不是在 中明确包含零是一个坏习惯.{0,5}

相关内容