【发布时间】:2014-03-14 09:35:55
【问题描述】:
下一个脚本
str=/aaa/bbb/ccc.txt
echo "str: $str"
echo ${str##*/} == $(basename $str)
echo ${str%/*} == $(dirname $str)
产生:
str: /aaa/bbb/ccc.txt
ccc.txt == ccc.txt
/aaa/bbb == /aaa/bbb
问题是:
- 在 bash 脚本中,何时建议使用命令
dirname和basename,何时使用变量替换,为什么?
问主要是因为:
str="/aaa/bbb/ccc.txt"
count=10000
s_cmdbase() {
let i=0
while(( i++ < $count ))
do
a=$(basename $str)
done
}
s_varbase() {
let i=0
while(( i++ < $count ))
do
a=${str##*/}
done
}
s_cmddir() {
let i=0
while(( i++ < $count ))
do
a=$(dirname $str)
done
}
s_vardir() {
let i=0
while(( i++ < $count ))
do
a=${str%/*}
done
}
time s_cmdbase
echo command basename
echo ===================================
time s_varbase
echo varsub basename
echo ===================================
time s_cmddir
echo command dirname
echo ===================================
time s_vardir
echo varsub dirname
在我的系统上产生:
real 0m33.455s
user 0m10.194s
sys 0m18.106s
command basename
===================================
real 0m0.246s
user 0m0.237s
sys 0m0.007s
varsub basename
===================================
real 0m30.562s
user 0m10.115s
sys 0m17.764s
command dirname
===================================
real 0m0.237s
user 0m0.226s
sys 0m0.007s
varsub dirname
调用外部程序(分叉)需要时间。问题的重点是:
- 使用变量替换而不是外部命令是否存在一些缺陷?
【问题讨论】:
-
我会说:
dirname和basename是用于此类非常精确情况的工具。变量替换适用于更一般的情况。因此,每当我想要目录名称时,我会使用dirname,当我需要文件名和变量替换时,我会使用basename,只要我需要更通用的东西而没有特定的工具来获取。 -
@fedorqui 我认为
dirname和basename更容易阅读,特别是对于那些不每天编写shell 的人(所以这是维护+1)但是性能差异是一个公平的观点。我认为,只要您在循环中需要它们(而不仅仅是在$0上),您就会考虑使用参数替换。 -
如果考虑性能(即花费大量时间做
dirname/basename),请使用参数扩展。 但是,如果可读性/稳健性更重要,则使用更简单/更容易/更易读的basename/dirname。通常更频繁地需要可读性......所以通常坚持使用basename/dirname。
标签: bash