我写了一个函数来帮助管理其他功能。但它严重缺乏效率。
首先我写这个函数来包装其他人。它从standard input
读取并将指定的function
应用于每个输入:
function func_pipe() {
local func="$1" && shift
while ifs='' read -r line || [[ -n "$line" ]]; do
$func $line
done
}
我定义了一个用于测试目的的模式:
PATTERN="mypattern"
我创建了一个10k行的大文件进行测试:
### Create big file
time for i in $(seq 1 10000); do
echo "$i - here I write the pattern $PATTERN for testing purpose.";
done > bigfile.txt
real 0m38.234s
user 0m10.245s
sys 0m20.050s
我编写了处理输入的函数:
function process1() {
echo -e "$@" | egrep "$PATTERN"
}
我处理文件以搜索模式。我使用func_pipe
来处理standard input
。 :
echo -e "\n[Testing with pipes]"
time cat bigfile.txt \
| func_pipe process1 \
| func_pipe process1 \
| wc -l
real 1m23.898s
user 1m16.992s
sys 1m54.495s
现在我将在一个字符串中构建我的命令,稍后再evaluate
。
首先,我编写了一个类似的处理函数,它将在一个字符串中打印管道。请注意使处理功能不同的下划线:
function _process1() {
echo " | grep \"\$PATTERN\""
}
我定义了我的命令和处理字符串:
cmd="cat bigfile.txt"
cmd_process="$(_process1)$(_process1) | wc -l"
我测试它们:
echo -e "\n[Testing with eval]"
time eval "${cmd}${cmd_process}"
real 0m0.014s
user 0m0.015s
sys 0m0.013s
它瞬间完成了它。因此,似乎管道功能和读取每个标准输入的效果确实不高效。至少,我想这个问题来自我的实施。我的目标是使它们与管道unix
命令(cut
,sed
,etc
)一样高效。我相信那些命令也是从stdin
读取的,所以我是缺少一些方法的人。缺少什么来改善我的包装功能?
答案 0 :(得分:2)
你的两种方法有一个主要区别:第二种方法只产生一个grep进程,它将从stdin读取整个文件,而你的第一种方法将为每个输入行产生一个grep进程。
我怀疑这是你观察到的差异的原因。产生一个过程很便宜但不是免费的。
由于shell(逐行读取+将每一行传递给子进程),第一个版本也会出现更多开销。
如果你想减少这种开销,你的func_pipe
应该将整个标准输入传递给process1
函数,而不是逐行分割它。
答案 1 :(得分:1)
只是读入bash的速度很慢,每个行也会分叉一个新进程。