3

这是为了简化我遇到的问题。我定义了一个设置变量的函数,这适用于这种情况:

$ function myfunc { res="ABC" ; }
$ res="XYZ"
$ myfunc
$ echo $res
    ABC

所以 res 已经被 myfunc 的调用改变了。但:

$ res="XYZ"
$ myfunc | echo
$ echo $res
    XYZ

因此,当 myfunc 是管道的一部分时,值不会改变。即使涉及管道,如何使 myfunc 以我想要的方式工作?

(在真正的脚本中,“myfunc”当然做了一些更精细的事情,管道的另一边有一个 zenity 进度对话而不是一个毫无意义的回声)

谢谢

4

2 回答 2

4

这在 Unix 上是不可能的。为了更好地理解这一点,您需要知道什么是变量。Bash 保留两个包含所有已定义变量的内部表。一种是用于当前 shell 的本地变量。set name=value您可以使用或仅创建那些name=value. 这些是流程本地的;创建新进程时,它们不会被继承。

要将变量导出到新的子进程,您必须使用export name. 这告诉 bash “我希望孩子们看到这个变量的值”。这是一项安全功能。

当您在 bash 中调用函数时,它会在当前 shell 的上下文中执行,因此它可以访问和修改所有变量。

但是管道是与 I/O 管道连接的进程列表。这意味着您的函数在 shell 中执行,并且只有这个 shell 的输出对echo.

即使导出myfunc也不起作用,因为导出仅适用于由您执行导出的 shell 启动的进程,并且echo由与以下相同的 shell 启动myfunc

bash
 +-- myfunc
 +-- echo

那是echo不是孩子的myfunc

解决方法:

  1. 将变量写入文件
  2. 使用更复杂的输出格式,如 XML 或多行输出,其中第一行输出始终是变量,真正的输出在下一行。
于 2012-07-10T08:06:08.433 回答
4

正如@Aaron 所说,问题是由在子shell 中运行的函数引起的。但是有一种方法可以在 bash 中避免这种情况,使用进程替换而不是管道:

myfunc > >(echo)

这与管道的作用大致相同,但 myfunc 在主 shell 中运行,而不是在子进程中运行。请注意,这是一个仅限 bash 的功能,您必须使用 #!/bin/bash 作为您的 shebang 才能使其工作。

于 2012-07-10T16:06:50.607 回答