多次快速替代grep文件?

时间:2016-09-03 21:18:37

标签: bash text grep

我目前使用长管道bash命令从这样的文本文件中提取数据,其中 $ f 是我的文件:

result=$(grep "entry t $t " $f | cut -d ' ' -f 5,19 | \
         sort -nk2 | tail -n 1 | cut -d ' ' -f 1)

我使用的脚本可以对 $ f 进行数百次类似的搜索,根据我提取的内容,以各种方式对所选行进行排序。我喜欢带有一堆管道的单行bash字符串,因为它紧凑而且容易,但它可能需要永远。有谁能建议更快的替代方案?也许是先将整个文件加载到内存中的东西?

由于

2 个答案:

答案 0 :(得分:0)

通过gawkawk执行asorti整个管道,您可能会得到提升:

contents="$(cat "$f")"
result="$(awk -vpattern="entry t $t" '$0 ~ pattern {matches[$5]=$19} END {asorti(matches,inds); print inds[1]}' <<<"$contents")"

这将读取&#34; $ f&#34;在变量中,我们将使用单个awk命令(好吧,gawk)来完成所有其余的工作。以下是它的工作原理:

  • -vpattern =&#34;条目t $ t&#34; :定义名为awk的{​​{1}}变量,其中包含shell变量pattern < / LI>
  • $ 0~pattern 将当前行与模式匹配,如果匹配,我们将在大括号中执行该部分,否则我们跳过它
    • 匹配[$ 5] = $ 19 在数组中添加一个条目(如果需要,创建数组),其中键是第5个字段,值是第19个
  • END 在处理完所有输入后执行以下功能
    • asorti(匹配,inds)t的条目进行排序,使matches是一个数组,其中包含inds中的键的顺序按排序顺序排列的值
    • print inds [1] 在与最低第19个字段相关联的匹配项中打印索引(即,之前为5美元)
  • &lt;&lt;&lt;&#34; $ contents&#34; matches处理shell变量awk中的值,就好像它是一个文件一样正在阅读

然后你可以只为每个模式更新模式,而不必每次都从磁盘读取文件,并且不需要为所有管道提供如此多的额外进程。

你必须进行基准测试才能确定它是否真的更快或更好,如果表现很重要,你真的应该考虑转移到正确的&#34;语言而不是shell脚本。

答案 1 :(得分:0)

由于您还没有提供示例输入/输出,这只是一个猜测,我只发布它,因为已经发布了您不应该做的其他答案,所以 - 这可能是你想要的那一行:

result=$(awk -v t="$t" '
    BEGIN { regexp = "entry t " t " " }
    $0 ~ regexp {
        if ( ($6 > maxKey) || (maxKey == "") ) {
            maxKey = $6
            maxVal = $5
        }
    }
    END { print maxVal }
' "$f")

我怀疑你的真正的性能问题不是那个脚本,而是你正在运行它,也许还有其他人在你没有向我们展示过的循环中。如果是,请参阅why-is-using-a-shell-loop-to-process-text-considered-bad-practice并发布更好的示例,以便我们为您提供帮助。