我有这个代码:
get_base() { echo "${1##*/}"; }
这很好,直到我们有1个或更多尾随斜线
我已经找到了如何修复它的解决方案,但问题是我们需要启用extglob
,而我没有想要:
ari@ari-gentoo ~ % x='/home/ari///'
ari@ari-gentoo ~ % echo "${x%%+(/)}"
/home/ari
然后我们可以obv将其保存到tmp var中,并运行basename对it的替代
不管怎样,我的问题是,有什么合适的方法吗而且它仍然很快(意味着不需要调用外部命令因为这个函数经常被调用(需要启用任何花哨的功能吗?
感谢您提前回答:(
问题和答案
- 在Bash中获取文件路径参数中的最后一个目录名/文件名是否回答了您的问题
no,因为所有这些解决方案要么使用命令,要么有一个只去掉最后一个斜杠而不是倍数的替换表达式:
- 你说的"适当"是什么意思
我的意思是"在不启用extglob或任何其他花哨功能的情况下实现">
这里有一种方法:
get_base() {
set -- "${1%"${1##*[!/]}"}"
printf '%sn' "${1##*/}"
}
$ get_base /home/oguz//
oguz
$ get_base /root
root
$ get_base /
$ get_base .bash_history
.bash_history
获取。。。在bash
作为对oguz-ismail正确答案的补充,我建议对这种函数使用-v
标志,以减少分叉:
get_base() {
if [[ $1 == -v ]] ;then
local -n _res=$2
shift 2
else
local _res
fi
set -- "${1%"${1##*[!/]}"}"
printf -v _res %s "${1##*/}"
[[ ${_res@A} == _res=* ]] && echo "$_res"
}
这让你可以通过尝试这个功能
$ get_base /path/entry////
entry
但为了将结果存储到某个变量中,您将避免像这样无用的fork
myvar=$(get_base /path/entry////)
并使用首选语法:
$ get_base -v myvar /path/entry////
$ echo $myvar
entry
要成为拆分entry
和path
的函数:
get_base() {
if [[ $1 == -v ]] ;then
local -n _res=$2
shift 2
else
local _res
fi
set -- "${1%"${1##*[!/]}"}"
printf -v _res %s "${1##*/}"
[[ ${_res@A} == _res=* ]] &&
echo "$_res" "${1%/$_res}" && return
printf -v _res[1] %s "${1%/$_res}"
}
然后:
$ get_base /path/to/entry////
entry /path/to
和
$ get_base -v myvar /path/to/entry////
$ declare -p myvar
declare -a myvar=([0]="entry" [1]="/path/to")
$ echo ${myvar[0]}
entry
$ echo ${myvar[1]}
/path/to
带分隔的unicode文件名:
$ get_base -v myvar '/path/to/some dir/some loved file ♥♥♥.xtns'
$ declare -p myvar
declare -a myvar=([0]="some loved file ♥♥♥.xtns" [1]="/path/to/some dir")
想法:
get_base() { [[ $1 =~ ([^/]*)/*$ ]]; echo "${BASH_REMATCH[1]}"; };
get_base() { while [[ "${1%/}" != "$1" ]]; do set -- "${1%%/}"; done; echo "${1##*/}"; }