4

这个 perldoc 页面

  1. 一起捕获命令的 STDERR 和 STDOUT:

    $output = `cmd 2>&1`;
  2. 要捕获命令的 STDOUT 但丢弃其 STDERR:

    $output = `cmd 2>/dev/null`;
  3. 要捕获命令的 STDERR 但丢弃其 STDOUT(此处排序很重要):

    $output = `cmd 2>&1 1>/dev/null`;
  4. 交换命令的 STDOUT 和 STDERR 以捕获 STDERR 但将其 STDOUT 保留为旧的 STDERR:

    $输出=`cmd 3>&1 1>&2 2>&3 3>&-`;

我不明白 3 和 4 是如何工作的,我也不太确定我对 1 和 2 的理解是否正确。以下是我的理解。请纠正我哪里错了。

我知道0和象征着1和。2STDINSTDOUTSTDERR

  1. 将 2 重定向到 1,以便它们现在都使用相同的流(&转义1以确保STDERR不会重定向到名为的文件1

  2. 将 2 (STDERR) 重定向到空流,使其被丢弃

  3. 我不明白这一点。难道不应该只是

    $output = `cmd 1>/dev/null`;

    此外,如果目标是在 获取STDERR消息STDOUT,不会1>/dev/null将所有内容重定向到/dev/null?

  4. 这里发生了什么?什么是流3?它像一个临时变量吗?

4

4 回答 4

3

虽然记录在 perldocs 中,但重定向都是标准的 linux 重定向。您正确理解了 1 和 2。

3)只有>STDOUT通常会被基本重定向(

4)cmd 3>&1 1>&2 2>&3 3>&-相当于

var tmp = STDOUT;
STDOUT = STDERR;
STDERR = tmp;
delete tmp;
于 2010-10-18T19:48:04.673 回答
3

真的,这些都不是 Perl —— 所有这些都由您使用反引号运算符调用的 shell 处理。所以你最好的读物是Unix 标准man shShell 章节

简而言之,对于#4:

  • 3>&1:打开 FD 3 以指向 stdout 当前指向的位置。
  • 1>&2: 重新打开 stdout 以指向 stderr 当前指向的位置。
  • 2>&3: 重新打开 stderr 以指向 FD 3 当前指向的位置,也就是在上一步完成之前stdout 指向的位置。现在 stdout 和 stderr 已成功交换。
  • 3>&-:关闭 FD 3,因为不再需要它。
于 2010-10-18T19:49:43.877 回答
3

通常我们有这个:

1-->STDOUT
2-->STDERR

2>&1将文件描述符重定向fd2fd1

1-->STDOUT
   /
2./

2>/dev/null重定向fd2/dev/null.

1-->STDOUT
2-->/dev/null

2>&1 1>/dev/null重定向fd2fd1,然后重定向fd1/dev/null

    /dev/null
   /
1./ STDOUT
   /
2./

3>&1 1>&2 2>&3 3>&-

  1. 首先将新的 fd 3 指向 fd 1 当前指向的任何位置(STDOUT)。
  2. 然后将 fd1 重定向到 fd2 当前指向的任何位置(STDERR),
  3. 然后将 fd 2 重定向到 fd 3 当前指向的任何位置(STDOUT)
  4. 然后关闭 fd3(3>&- 表示关闭文件描述符 3)。

整个事情有效地交换了 fd1 和 fd2。fd3 充当临时变量。

1 --STDOUT
 X
2 `-STDERR

有关 IO 重定向的更多信息,请参阅文档

于 2010-10-18T19:53:44.930 回答
-2

3.没有。排序很重要,因此它摆脱了原始标准输出,然后将标准错误移动到标准输出。

4.3只是另一个文件描述符,与前3个相同。大多数进程总共可以使用256个不同的文件描述符。

于 2010-10-18T19:45:28.927 回答