加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Bash变量替换vs dirname和basename

发布时间:2020-12-16 01:40:16 所属栏目:安全 来源:网络整理
导读:下一个脚本 str=/aaa/bbb/ccc.txtecho "str: $str"echo ${str##*/} == $(basename $str)echo ${str%/*} == $(dirname $str) 生产: str: /aaa/bbb/ccc.txtccc.txt == ccc.txt/aaa/bbb == /aaa/bbb 问题是: 在bash脚本中,何时建议使用命令dirname和basename
下一个脚本

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

调用外部程序(分叉)需要花费时间.问题的要点是:

>使用变量替换而不是外部命令是否存在一些缺陷?

解决方法

外部命令进行一些逻辑更正.检查下一个脚本的结果:

doit() {
    str=$1
    echo -e "string   $str"
    cmd=basename
    [[ "${str##*/}" == "$($cmd $str)" ]] && echo "$cmd same: ${str##*/}" || echo -e "$cmd different ${str##*/}t>${str##*/}<tvs command:t>$($cmd $str)<"
    cmd=dirname
    [[ "${str%/*}"  == "$($cmd $str)" ]] && echo "$cmd  same: ${str%/*}" || echo -e "$cmd  different ${str%/*}t>${str%/*}<tvs command:t>$($cmd $str)<"
    echo
}

doit /aaa/bbb/
doit /
doit /aaa
doit aaa
doit aaa/
doit aaa/xxx

结果

string   /aaa/bbb/
basename different ${str##*/}   ><          vs command: >bbb<
dirname  different ${str%/*}    >/aaa/bbb<  vs command: >/aaa<

string   /
basename different ${str##*/}   ><  vs command: >/<
dirname  different ${str%/*}    ><  vs command: >/<

string   /aaa
basename same: aaa
dirname  different ${str%/*}    ><  vs command: >/<

string   aaa
basename same: aaa
dirname  different ${str%/*}    >aaa<   vs command: >.<

string   aaa/
basename different ${str##*/}   ><  vs command: >aaa<
dirname  different ${str%/*}    >aaa<   vs command: >.<

string   aaa/xxx
basename same: xxx
dirname  same: aaa

最有趣的结果之一是$(dirname“aaa”).外部命令dirname正确返回.但变量扩展${str%/ *}返回不正确的值aaa.

替代演示

脚本:

doit() {
    strings=( "[[$1]]"
    "[[$(basename "$1")]]"
    "[[${1##*/}]]"
    "[[$(dirname "$1")]]"
    "[[${1%/*}]]" )
    printf "%-15s %-15s %-15s %-15s %-15sn" "${strings[@]}"
}


printf "%-15s %-15s %-15s %-15s %-15sn" 
    'file' 'basename $file' '${file##*/}' 'dirname $file' '${file%/*}'

doit /aaa/bbb/
doit /
doit /aaa
doit aaa
doit aaa/
doit aaa/xxx
doit aaa//

输出:

file            basename $file  ${file##*/}     dirname $file   ${file%/*}     
[[/aaa/bbb/]]   [[bbb]]         [[]]            [[/aaa]]        [[/aaa/bbb]]   
[[/]]           [[/]]           [[]]            [[/]]           [[]]           
[[/aaa]]        [[aaa]]         [[aaa]]         [[/]]           [[]]           
[[aaa]]         [[aaa]]         [[aaa]]         [[.]]           [[aaa]]        
[[aaa/]]        [[aaa]]         [[]]            [[.]]           [[aaa]]        
[[aaa/xxx]]     [[xxx]]         [[xxx]]         [[aaa]]         [[aaa]]        
[[aaa//]]       [[aaa]]         [[]]            [[.]]           [[aaa/]]

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读