【问题标题】:Is there a way to only require one echo in this scenario?有没有办法在这种情况下只需要一个回声?
【发布时间】:2020-03-13 13:17:19
【问题描述】:

我有以下代码行:

for h in "${Hosts[@]}" ; do echo "$MyLog" | grep -m 1 -B 3 -A 1 $h >> /LogOutput ; done

我的 hosts 变量是一大堆主机

有没有更好的方法来做到这一点,不需要我在每个循环上回显?像 grep 一样代替变量?

【问题讨论】:

  • 你不用回显,把echo "$MyLog" | grep -m 1 -B 3 -A 1 $h换成grep -m 1 -B 3 -A 1 $h <<< "$MyLog"
  • @WiktorStribiżew 这有使用临时文件而不是内存管道缓冲区的副作用(我相信)。
  • 您想在 LogOutput 中保持相同的顺序吗?如果没有,您似乎只想使用更好的模式来匹配多个字符串。无论哪种方式,似乎 awk 的一次通行证就是您想要的。
  • @WiktorStribiżew 感谢 Wiktor,我以为我已经尝试过这个,但由于非常密集且需要很长时间才能完成而忽略了它。但我又试了一次,几乎是瞬间的,所以我一定是尝试过别的东西。
  • 为什么log在一个变量开头?

标签: bash for-loop grep


【解决方案1】:

没有echo,没有循环

#!/bin/bash
hosts=(host1 host2 host3)
MyLog="
asf host
sdflkj
sadkjf
sdlkjds
lkasf
sfal
asf host2
sdflkj
sadkjf
"
re="${hosts[@]}"
egrep -m 1 -B 3 -A 1 ${re// /|} <<< "$MyLog"

带有一个echo的变体

echo "$MyLog" | egrep -m 1 -B 3 -A 1 ${re// /|}

用法

$ ./test
sdlkjds
lkasf
sfal
asf host2
sdflkj

【讨论】:

  • 将 egrep 输出到文件时如何工作?我试过 egrep -m 1 -B 3 -A 1 ${re// /|} /LogOutput 但这不起作用,只有第一个 egrep 项目被记录
  • 看来我没有理解你的想法,-m 1 需要删除或添加循环。
【解决方案2】:

一个echo,没有循环,所有的grepping都是并行完成的,使用GNU Parallel

echo "$MyLog"  | parallel -k --tee --pipe 'grep -m 1 -B 3 -A 1 {}' ::: "${hosts[@]}"

-k 保持输出有序。 --tee--pipe 确保stdin 被复制到所有进程。 并行运行的进程用单引号括起来。

【讨论】:

    【解决方案3】:

    printf你的字符串到多行,然后grep可以吗?比如:

    printf '%s\n' "${Hosts[@]}" | grep  -m 1 -B 3 -A 1 $h >> /LogOutput
    

    【讨论】:

      【解决方案4】:

      假设您使用的是 GNU 系统。否则info grep

      来自grep --help

      grep --help | head -n1
      

      输出

      Usage: grep [OPTION]... PATTERN [FILE]...
      

      所以照着做就可以了。

      for h in "${Hosts[@]}" ; do grep -m 1 -B 3 -A 1 "$h" "$MyLog" >> /LogOutput ; done
      

      【讨论】:

        猜你喜欢
        • 2022-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-23
        • 2018-06-24
        • 1970-01-01
        • 1970-01-01
        • 2012-03-31
        相关资源
        最近更新 更多