gpt4 book ai didi

bash - 了解 bash 中的嵌套进程替换,以及一点点 awk

转载 作者:行者123 更新时间:2023-11-29 09:32:36 24 4
gpt4 key购买 nike

我似乎无法弄清楚,这里发生了什么。我有相同代码的 4 个版本,唯一的区别是代码块/行的顺序。我最初的期望是重定向顺序没有任何区别,但它似乎不正确。我还假设 >() 具有一些文件描述符阴谋的屏蔽属性,但没有...

请不要问我用它做什么,也不需要替代解决方案,我想了解这段代码。否则我对我对流程替代的理解的信念将永远被打破......

元代码:

1_cmd_producing_both_stdout_and_stderr
|
+-stdout-> 2_cmd_producing_both_stdout_and_stderr
| |
| +-stdout-> A_awk_writing_stdout_to_file_producing_stderr
| |
| +-stderr-> B_awk_writing_stdout_to_file_producing_stderr
|
+-stdout-> 3_cmd_producing_both_stdout_and_stderr
|
+-stdout-> C_awk_writing_stdout_to_file_producing_stderr
|
+-stderr-> D_awk_writing_stdout_to_file_producing_stderr

版本 1:1 2 A B 3 C D

版本 2:1 2 B A 3 D C

版本 3:1 3 D C 2 B A

版本 4:1 3 C D 2 A B

注意:

我试过了2个和2 B A,它们也产生一致的输出,类似于版本 1。

awk:GNU Awk 4.1.1,API:1.1(GNU MPFR 3.1.2-p3,GNU MP 6.0.0)

狂欢:GNU bash,版本 4.3.30(1)-release (x86_64-pc-linux-gnu)

版本 1,这会产生我期望的输出:

( echo log; echo err 1>&2; ) \
1> >( ( echo -n '1.'; cat; echo '1.ERR' 1>&2 ; ) \
1> >( awk 'BEGIN { print "error 1" >"/dev/stderr" } { print $0 }' >out.out ) \
2> >( awk 'BEGIN { print "error 2" >"/dev/stderr" } { print $0 }' >out.err )
) \
2> >( ( echo -n '2.'; cat; echo '2.ERR' 1>&2 ; ) \
1> >( awk 'BEGIN { print "error 3" >"/dev/stderr" } { print $0 }' >err.out ) \
2> >( awk 'BEGIN { print "error 4" >"/dev/stderr" } { print $0 }' >err.err )
)

文件内容:

out.out 1.log
out.err 1.ERR
err.out 2.err
err.err 2.ERR

输出:

error 4
error 2
error 1
error 3

版本 2:

注意:与版本 1 相比,第 1 与第 2、第 3 与第 4 的第二级缩进线互换。

( echo log; echo err 1>&2; ) \
1> >( ( echo -n '1.'; cat; echo '1.ERR' 1>&2 ; ) \
2> >( awk 'BEGIN { print "error 1" >"/dev/stderr" } { print $0 }' >out.err ) \
1> >( awk 'BEGIN { print "error 2" >"/dev/stderr" } { print $0 }' >out.out )
) \
2> >( ( echo -n '2.'; cat; echo '2.ERR' 1>&2 ; ) \
2> >( awk 'BEGIN { print "error 3" >"/dev/stderr" } { print $0 }' >err.err ) \
1> >( awk 'BEGIN { print "error 4" >"/dev/stderr" } { print $0 }' >err.out )
)

文件内容:

(!) out.err error 2\n1.ERR
out.out 1.log
(!) err.err 2.ERR\nerror 4
err.out 2.err

输出:

error 3
error 1

版本 3:

注意:与版本 2 相比,第一级缩进代码块已交换。

( echo log; echo err 1>&2; ) \
2> >( ( echo -n '2.'; cat; echo '2.ERR' 1>&2 ; ) \
2> >( awk 'BEGIN { print "error 1" >"/dev/stderr" } { print $0 }' >err.err ) \
1> >( awk 'BEGIN { print "error 2" >"/dev/stderr" } { print $0 }' >err.out )
) \
1> >( ( echo -n '1.'; cat; echo '1.ERR' 1>&2 ; ) \
2> >( awk 'BEGIN { print "error 3" >"/dev/stderr" } { print $0 }' >out.err ) \
1> >( awk 'BEGIN { print "error 4" >"/dev/stderr" } { print $0 }' >out.out )
)

文件内容:

(!) err.err error 2\n2.ERR
(!) err.out 2.err\nerror 3
(!) out.err 1.ERR\nerror 4
out.out 1.log

输出:

error 1
(!)

版本 4:

注意:与版本 3 相比,第 1 与第 2、第 3 与第 4 的第二级缩进线互换。

( echo log; echo err 1>&2; ) \
2> >( ( echo -n '2.'; cat; echo '2.ERR' 1>&2 ; ) \
1> >( awk 'BEGIN { print "error 1" >"/dev/stderr" } { print $0 }' >err.out ) \
2> >( awk 'BEGIN { print "error 2" >"/dev/stderr" } { print $0 }' >err.err )
) \
1> >( ( echo -n '1.'; cat; echo '1.ERR' 1>&2 ; ) \
1> >( awk 'BEGIN { print "error 3" >"/dev/stderr" } { print $0 }' >out.out ) \
2> >( awk 'BEGIN { print "error 4" >"/dev/stderr" } { print $0 }' >out.err )
)

文件内容:

(!) err.out 2.err\nerror 4\nerror 3
err.err 2.ERR
out.out 1.log
out.err 1.ERR

输出:

error 2
error 1
(!)

版本 2、3、4 发生了什么??

最佳答案

您认为输出重定向的顺序无关紧要的假设是不正确的。秩序很重要。让我们只考虑代码示例 2 中的字符串“error 2”,看看为什么它被写入文件 out.err。代码是:

( echo log; echo err 1>&2; ) \
1> >( ( echo -n '1.'; cat; echo '1.ERR' 1>&2 ; ) \
2> >( awk 'BEGIN { print "error 1" >"/dev/stderr" } { print $0 }' >out.err ) \
1> >( awk 'BEGIN { print "error 2" >"/dev/stderr" } { print $0 }' >out.out )
) \
2> >( ( echo -n '2.'; cat; echo '2.ERR' 1>&2 ; ) \
2> >( awk 'BEGIN { print "error 3" >"/dev/stderr" } { print $0 }' >err.err ) \
1> >( awk 'BEGIN { print "error 4" >"/dev/stderr" } { print $0 }' >err.out )
)

字符串“error 2”由进程 B 写入其 stderr。由于 shell 解析以启动进程 B 的字符串不包含到 stderr 的重定向,因此进程 B 从其父进程继承其 stderr。它的父级是您标记为 2 的子 shell。该进程有 2 个重定向,每个重定向到子进程。在进程 B 启动时,进程 2 的 stderr 已被定向到进程 A,因此进程 B 将在此处写入字符串。进程 A 读取它并将字符串写入其标准输出,即文件 out.err。如果颠倒重定向的顺序,那么进程 2 的 stderr 还没有被重定向,所以进程 B 的 stderr 将与进程的 stderr 相同发起进程(例如,您的 tty)

关于bash - 了解 bash 中的嵌套进程替换,以及一点点 awk,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45002425/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com