【问题标题】:Why does piping keep collapsing functions from keeping its new definition?为什么管道使折叠功能无法保持其新定义?
【发布时间】:2012-10-15 16:24:29
【问题描述】:

在 Bash-Hackers.org 上有一个关于折叠函数的 nice little wiki entry。基本上,折叠函数是根据某些条件重新定义自身的函数。基本示例如下所示:

chatter() {
  if [[ $verbose ]]; then
    chatter() {
      echo "$@"
    }
    chatter "$@"
  else
    chatter() {
      :
    }
  fi
}

我认为这是一个不错的小技巧,可能对创建如下函数很有用:

# a portable extended regular expression sed for Linux and Mac
# simply checks if using an option fails for one version
# @see http://wiki.bash-hackers.org/howto/collapsing_functions
my_sed() {
    if ( echo abc | sed -r /abd/p > /dev/null 2>/dev/null ) ; then 
        #we are running a GNU version. redefine function
        echo gnu
        my_sed() {
            sed -r "$@"
        }
    else 
        #we are running another version. defaulting to BSD
        #redefining function
        echo osx
        my_sed() {
            sed -E "$@"
        }
    fi
    my_sed "$@"
}

(echo 语句仅用于调试 btw)。这在以my_sed "s/foo/bar" /tmp/somefile.txt 运行时按预期工作,第一次输出“gnu”(在 Linux 上,在 Mac 上为 osx),然后在后续运行中保持沉默。但是,如果我只是在管道中使用该函数,则该函数不会被重新定义,而是不断输出“gnu”。示例:echo 123 | my_sed 's/foo/bar' 每次在 shell 中运行时都会输出“gnu”。

这是为什么?管道对当前上下文/shell 做了什么使函数无法保持其新定义?管道是否每次都分叉一个新进程,从而导致新定义从原始 shell 中丢失?

【问题讨论】:

    标签: bash unix scripting


    【解决方案1】:

    管道在子shell中运行,子shell退出时重新定义丢失。

    【讨论】:

    • 如果您使用 bash 4.2 或更高版本(您必须在 Mac OS X 上确定升级,因为它附带 3.2),您可以在调用 my_sed 第一个之前使用 shopt -s lastpipe时间,这将导致管道中的最后一个命令在当前 shell 中运行,而不是在子 shell 中。这可能会解决问题。
    • 很好的提示,但不幸的是,即使是 OS X 10.6(2010 年发布)也使用 2007 年的 Bash 版本(版本 3.2.48)...
    • 甚至 OS X 10.8(2012 年秋季发布)使用旧的 3.2 版本:-/
    猜你喜欢
    • 2015-09-19
    • 1970-01-01
    • 2021-03-27
    • 2015-04-18
    • 2023-03-12
    • 2021-03-13
    • 2020-03-13
    • 1970-01-01
    相关资源
    最近更新 更多