AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 437551
Accepted
Brad Parks
Brad Parks
Asked: 2018-04-14 07:10:05 +0800 CST2018-04-14 07:10:05 +0800 CST 2018-04-14 07:10:05 +0800 CST

如何等待程序完成,并在完成后将标准输入管道传输到标准输出?

  • 772

我试图弄清楚如何等待命令完成,然后将标准输入通过管道传输到标准输出。我在mac上,但我认为我的问题更多是关于如何等待进程完成和管道输出,然后是与mac有关的任何事情。

我注意到在 mac 上,我可以一起运行几个say命令,如果我使用操作符将它们​​连接起来,它们会等待每个短语完全说出,然后再开始下一个&&。

$ say "stage 1" && say "stage 2"

这就是真正的用例所在——我有一个 bash 脚本,我想让它在它说完之后将它传递给 stdout 。

$ cat /etc/passwd | say_and_pass "stage 1" | grep -v test | say_and_pass "stage 2"

所以从概念上讲,这会大声说“阶段 1”,然后立即说“阶段 2”,然后将 grepped 的内容转储/etc/password到标准输出。

我最初对say_and_pass脚本的破解是这样的:

say_and_pass

#!/usr/bin/env bash
OUT="$*"
say "$OUT" && cat 

但这似乎不起作用;-)

编辑:我将上面的示例更改为say_and_pass "stage2"用作最终命令,这是我的解决方案工作所必需的......

bash
  • 6 6 个回答
  • 10760 Views

6 个回答

  • Voted
  1. DopeGhoti
    2018-04-14T07:48:14+08:002018-04-14T07:48:14+08:00

    这就是真正的用例所在——我有一个 bash 脚本,我想让它在它说完之后将它传递给 stdout。

    $ cat /etc/password | say_and_pass "stage 1" | grep -v test | say "stage 2"
    

    您在这里尝试做的问题是您似乎有两个数据流——一个say用于文本处理,一个用于文本处理(即cat和grep)。

    您不能为此使用单个管道,因为它只会混合数据。 cat /etc/passwd | say将使您的计算机尝试说出文件的全部内容。此外,say不会向标准输出写入任何内容,因此不会再往下流。

    如果您确实想“中断”您的数据处理流以处理对其他实用程序的单独输出,例如say,您需要为您的一个或另一个数据流设置一个 FIFO(即“命名管道”),或者使用写入磁盘的临时文件。

    您的演示用例对示例没有多大帮助,因为尽管有says,但您只是在ping 一个文件,这可以通过(是无用的使用grep)一步完成。grep -v test /etc/passwdcat file | grep patterncat

    综上所述,一个使用暂存文件的示例:

    scratch=$(mktemp)
    trap "rm -f $scratch" EXIT
    cat /etc/passwd > $scratch
    say "Stage one"
    grep -v test $scratch
    say "Stage two"
    

    还有一个使用命名管道say:

    mkfifo youtalktoomuch
    say youtalktoomuch &
    exec 3> youtalktoomuch
    do_thing_one
    echo "Stage one" > youtalktoomuch
    do_thing_two
    echo "Stage two" > youtalktoomuch
    exec 3>&-
    rm youtalktoomuch
    
    Once again, though, if you need to connect the output of `do_thing_one` to the input of `do_thing_two` without piping one into the other, you will need to use either another named pipe or a scratch file on disk to hold the data.
    
    • 1
  2. Brad Parks
    2018-04-14T11:42:56+08:002018-04-14T11:42:56+08:00

    原来我所要做的就是在我的脚本开始时消耗所有的标准输入......我不希望它在收到标准输入时处理它,但是当管道链中的整个前一个命令完成时。

    所以我的say_and_pass脚本就是这个,它适用于我的用例!

    #!/usr/bin/env bash
    
    OUT=$(cat -)
    
    MSG="$*"
    say "$MSG"
    
    echo "$OUT"
    
    • 0
  3. agc
    2018-04-14T11:51:04+08:002018-04-14T11:51:04+08:00

    尝试:

    say "stage 1" && cat /etc/passwd  |  { say "stage 2" && grep -v test ; }
    

    我的系统上实际上没有say,但这有效:

    espeak "stage 1" && cat /etc/passwd  |  { espeak "stage 2" && grep -v test ; }
    
    • 0
  4. Luís Fernando Quitaiski
    2019-01-26T05:14:54+08:002019-01-26T05:14:54+08:00

    H!

    我建议,根据您自己的回答,将标准输入转储到标准输出,删除将其存储到变量的部分。这应该会减少内存消耗,并使管道链像管道一样工作(一条线,它被处理,并将结果发送到下一个进程)。

    #!/usr/bin/env bash
    
    MSG="$*"
    say "$MSG"
    
    cat -
    
    • 0
  5. Best Answer
    Walter
    2021-09-29T21:43:57+08:002021-09-29T21:43:57+08:00

    这个版本say_and_pass可以满足 OP 的要求:

    #!/usr/bin/env bash
    
    # Create a temporary file to store stdin
    TEMP_STDIN="$(mktemp)"
    
    # Capture stdin and save it to temporary file
    cat - > "${TEMP_STDIN}"
    
    # say message, but prevent any output to stdout
    say "$@" > /dev/null
    
    # Dump saved stdin to stdout
    cat "${TEMP_STDIN}"
    
    # Clean up, but prevent any output to stdout
    rm -f "${TEMP_STDIN}" > /dev/null
    

    它使用一个临时文件,就像@DopeGhoti 建议的那样,但将任何其他逻辑(grep例如,)保留在脚本之外。这使得它say_and_pass更加通用和可重用。

    我对目标/目的的解释是,我们需要一种可听的方式来监控可能较长的管道的进度。

    所以运行时:

    cmd1 | say_and_pass "stage 1" | cmd2 | say_and_pass "stage 2"
    

    作为用户,您可以听得见cmd1已完全执行完毕;权衡是在完成cmd2之前无法开始处理其标准输入cmd1。但似乎 OP 意识到了这种权衡并愿意这样做。

    这类似于@BradParks 的答案,但不受 bash 可用内存的限制(正如@agc 指出的那样),并且在避免意外污染标准输出方面更加小心。

    另请注意,无需将消息捕获到自己的变量中,因此我们也只需转发"$@"到say.

    • 0
  6. Muhammed Tayyib Kılıç
    2018-04-14T07:39:09+08:002018-04-14T07:39:09+08:00
    #!/usr/bin/env bash
    OUT="$*"
    say "$OUT" | cat -
    

    如果你使用&&,它的意思是,在执行第二个命令之后执行第一个命令,但第一个命令的结果对于第二个命令并不重要。我的意思是你有 2 个不同的命令,因为你使用 &&。如果你使用 |,它的意思是第一个命令做某事并为第二个命令提供一些东西。最后,您应该为 cat 命令提供一个属性。顺便说一句对不起我的英语

    • -3

相关问题

  • 通过命令的标准输出以编程方式导出环境变量[重复]

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve