用于 grepping 的重定向和管道

ice*_*itz 1 grep bash io-redirection tee

我正在编写一个脚本,该脚本将运行输出到 STDOUT 的校验和过程,然后我想 grep 匹配 OK 或 FAILED 的行,并用这些匹配做不同的事情(即输出到终端和日志)。我已经观看了大量的 Youtube 视频并阅读了大量关于重定向的内容,但我似乎无法理解重定向究竟是如何工作的。我想要做的是将 STDOUT 链接到多个 grep 而不让它们吞噬不匹配的文本。

这是我尝试使用 cat 而不是 md5sum 的概念,每行都有一个动物名称的文本文件(DOG、CAT、PONY、RHINO、DEER、FOX):

{ cat test.txt 3>&1 | tee /dev/fd/3 | grep DOG; } 3> results.txt

这符合我的期望。我在这里的理解是我在文件上做一只猫,然后打开 fd3,它指向写入 STDOUT(fd1) 的任何内容。由于 grep 会吞噬 fd1 中的所有内容,因此我将 cat 的 STDOUT 明确地发送到 fd3,然后通过管道将 STDOUT 传送到 grep。Grep 将打印出匹配 DOG 的行,然后所有从 cat 写入 fd3 的文本将被推送到 results.txt 文件中。

现在,要链接另一个 grep 以查找其他文本,我必须将 fd3 数据指向回 STDOUT,将其明确返回 fd3,然后通过管道将 STDOUT 传输到新的 grep。

{ { cat test.txt 3>&1 | tee /dev/fd/3 | grep DOG; } 3>&1 | tee /dev/fd/3 | grep PONY; } 3> results.txt

这里的第一个问题是第一个 grep 的 STDOUT 被第二次推入 fd3,而不是打印到终端。所以现在我的 results.txt 得到了重复,我从来没有在第一个 grep 的屏幕上打印任何东西。这就是我对重定向的理解崩溃的地方。我有点明白发生了什么,但我想不出一个简单的解决方案。

我想 grep STDOUT,将结果打印到屏幕上,然后将原始文本传递给另一个 grep,也许是第三个、第四个等等,而不修改我传递给每个 GREP 的原始文本,并且没有每个后续的 grep 吃掉应该打印到屏幕上的前一个'匹配。

我可能可以通过存储一个变量并在多行 grep 上调用它来做到这一点,但是我必须等待整个第一个命令完成。对于我正在处理的应用程序,我希望在校验和期间查看实时结果,而不仅仅是在整个过程完成前一个小时的空白屏幕。任何关于我做错了什么的澄清都会非常有帮助,谢谢!

编辑

我知道 cat 的这种确切用法毫无意义,我只是用它来演示这个概念。在我将应用这个概念的脚本中,第一个命令实际上是:

md5sum -c checksum.md5

它将读取校验和文件,重新散列源并输出到 STDOUT 一个通过/失败行。然后我想 grep 这个流并将结果发送到单独的日志和/或终端输出 - 但 cat 似乎是一种更简单的方法来演示这个问题,因为这可以应用于过滤任何命令和 grepping 流,例如 find、md5 , ls 等

ImH*_*ere 5

您可以更好地使用流程替换来完成您的要求:

  1. 尽可能接近您的原始命令:

    cat test.txt | tee >(grep DOG) >(grep PONY) >results.txt
    
    Run Code Online (Sandbox Code Playgroud)
  2. 去除 cat 的无用使用:

    <test.txt tee >(grep DOG) >(grep PONY) >results.txt
    
    Run Code Online (Sandbox Code Playgroud)

    或者:

    tee >(grep DOG) >(grep PONY) <test.txt >results.txt
    
    Run Code Online (Sandbox Code Playgroud)