shell 重定向的一处妙用
by 王 聪
at 2011-10-18 11:41:30
original http://wangcong.org/blog/archives/1780
偶然在 dracut 的代码中发现一个使用重定向很巧妙的地方。见 modules.d/90kernel-modules/module-setup.sh 文件。
之前的老代码是这样的:
BASH:
-
##
-
local _f
-
while read _f; do case "$_f" in
-
*.ko) [[ $(< $_f) =~ $_blockfuncs ]] && echo "$_f" ;;
-
*.ko.gz) [[ $(gzip -dc <$_f) =~ $_blockfuncs ]] && echo "$_f" ;;
-
esac
-
done
意思很清楚吧?就是在内核模块(注意是二进制格式)中匹配一些函数(字符串)。这样会很慢,因为 bash 要在庞大的二进制文件流中匹配一些指定字符串。
于是,就有人想了一个方法加速这个处理过程,把原来的单个数据流分成两个并行的数据流,同时进行匹配!很巧妙!
BASH:
-
##
-
function bmf1() {
-
local _f
-
while read _f; do case "$_f" in
-
*.ko) [[ $(< $_f) =~ $_blockfuncs ]] && echo "$_f" ;;
-
*.ko.gz) [[ $(gzip -dc <$_f) =~ $_blockfuncs ]] && echo "$_f" ;;
-
esac
-
done
-
}
-
# Use two parallel streams to filter alternating modules.
-
local merge side2
-
( ( local _f1 _f2
-
while read _f1; do echo "$_f1"
-
if read _f2; then echo "$_f2" 1>&${side2}; fi
-
done \
-
| bmf1 1>&${merge} ) {side2}>&1 \
-
| bmf1 ) {merge}>&1
经过 refactor 之后的或许更好理解一些:
BASH:
-
# subfunctions inherit following FDs
-
local _merge=8 _side2=9
-
function bmf1() {
-
local _f
-
while read _f; do case "$_f" in
-
*.ko) [[ $(< $_f) =~ $_blockfuncs ]] && echo "$_f" ;;
-
*.ko.gz) [[ $(gzip -dc <$_f) =~ $_blockfuncs ]] && echo "$_f" ;;
-
esac
-
done
-
}
-
function rotor() {
-
local _f1 _f2
-
while read _f1; do
-
echo "$_f1"
-
if read _f2; then
-
echo "$_f2" 1>&${_side2}
-
fi
-
done | bmf1 1>&${_merge}
-
}
-
# Use two parallel streams to filter alternating modules.
-
eval "( ( rotor ) ${_side2}>&1 | bmf1 ) ${_merge}>&1"