在 Bash-Hackers.org 上有一个关于折叠函数的不错的小 wiki 条目。基本上,折叠函数是根据某些条件重新定义自身的函数。基本示例如下所示:
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 "$@"
}
(回声语句仅用于调试顺便说一句)。这在运行时按预期工作my_sed "s/foo/bar" /tmp/somefile.txt
,第一次输出“gnu”(在 Linux 上,在 Mac 上 osx),然后在后续运行中保持沉默。但是,如果我只是在管道中使用该函数,则该函数不会被重新定义,而是不断输出“gnu”。示例:echo 123 | my_sed 's/foo/bar'
每次在 shell 中运行时都会输出“gnu”。
为什么是这样?管道对当前上下文/shell 做了什么使函数无法保持其新定义?管道是否每次都分叉一个新进程,以便新定义从原始外壳中丢失?