OS X:如何在600mb json文件中有效查找周围100个字符上下文的文本?

时间:2017-04-05 10:45:33

标签: macos grep

我有一个较大的缩小text.json文件,我需要在其中找到特定的短语dasdhfb347rbf并打印出周围的短语grep -Eo '.{0,100}dasdhfb347rbf.{0,100}' /dir/text.json。 100个字符上下文(前导/尾随)。

我已经尝试hawtio.proxyWhitelist,但它似乎永远都会挂起。

PS。我有一个带有i7 cpu,8GB内存和SSD驱动器的macbook。

3 个答案:

答案 0 :(得分:2)

正如Mark Setchell在his answer中指出的那样,您在{中使用(未转义)}.{0,100}来匹配多达100个字符。需要使用-E来启用扩展正则表达式(正则表达式);或者,您可以使用转义(使用默认的基本正则表达式):.\{0,100\}

但是,两种更正都无法解决您的问题,即 性能问题:要grep整个文件 - 因为它是缩小 JSON - 是单行 您的特定正则表达式导致执行时间非常长(取决于您的硬件,在使用600MB文件的10+ 分钟的顺序;据推测,您的正则表达式需要大量的回溯)。

Yreg's answer中的建议使用LC_ALL=C会略有改进,但不足以产生真正的差异(LC_ALL=C简化了字符处理,因为每个字节都被假定为是一个ASCII字符。)

切换到文字字符串匹配可大幅提升效果,但grep支持文字匹配,但不支持报告基于字符的上下文(仅限基于行的)。

因此使用的工具是awk ,它提供了文字字符串匹配和基于位置的子字符串提取功能:

awk -v RS='\3' -v txt='dasdhfb347rbf' -v n=100 '
  BEGIN { 
    getline; s = $0               # read the entire file
    while (pos=index(s, txt)) {   # loop over matches
      len = length(txt) + 2 * n - (pos - n < 1 ? n - pos + 1 : 0)
      print substr(s, pos-n, len)
      s = substr(s, pos -n + len)
    }
  }
' text.json

上述情况应该会好得多。

请注意,需要v RS='\3'才能使BSD Awk立即读取整个文件(-v RS='^$'通常与GNU Awk和Mawk一起使用,但这不适用于BSD Awk);请注意,此技术依赖于控件字符0x3不属于文本。

旁注:

  • GNU 您可以通过Homebrew安装的Awk,比我机器上的BSD Awk快两倍多。

  • Mawk(也可以通过Homebrew安装),这通常是最快的Awk,这里不是一个选项,因为它似乎对行长度有一个硬限制。

答案 1 :(得分:0)

尝试更改区域设置。

LC_ALL=C grep -o…

答案 2 :(得分:0)

我认为你需要在macOS上使用-E选项来允许使用扩展的正则表达式:

# without "-E", finds nothing
echo abcdefghijk | grep -o ".def.{3}"

# with "-E", finds regex
echo abcdefghijk | grep -Eo ".def.{3}"
cdefghi