gpt4 book ai didi

Bash 变量替换与目录名和基名

转载 作者:行者123 更新时间:2023-11-29 08:44:40 25 4
gpt4 key购买 nike

下一个脚本

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 脚本中,何时建议使用命令 dirnamebasename 以及何时进行变量替换以及为什么?

主要是因为:

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

调用外部程序( fork )会花费时间。问题的要点是:

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

最佳答案

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

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 %-15s\n" "${strings[@]}"
}


printf "%-15s %-15s %-15s %-15s %-15s\n" \
'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/]]

关于Bash 变量替换与目录名和基名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22401091/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com