我有这个代码:
get_base() { echo "${1##*/}"; }
这一切正常,直到我们有 1 个或多个 尾部斜杠
我已经找到了如何修复它的解决方案,但是 问题是我们需要启用
extglob
,但我不需要
想要那个:
ari@ari-gentoo ~ % x='/home/ari///'
ari@ari-gentoo ~ % echo "${x%%+(/)}"
/home/ari
然后我们可以将其保存到 tmp var 中并运行基本名称 替换它
无论如何,我的问题是,有没有合适的方法可以做到这一点 而且它仍然很快(意味着没有调用外部命令 因为这个函数被调用了很多)而不 需要启用任何奇特的功能吗?
谢谢您的提前答复:)
否,因为所有这些解决方案要么使用命令,要么具有仅删除最后一个斜杠而不是多个斜杠的替换表达式:)(例如 /home/ari/// 带有 expr ${x%/} 将仅变为 /home/ari // 当它需要是 /home/ari 时)
我所说的“正确”是指“在不启用 extglob 或任何其他奇特功能的情况下实现的”
get_base() {
set -- "${1%"${1##*[!/]}"}"
printf '%s\n' "${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
但是为了将结果存储到某个变量中,你会避免无用的分叉,就像
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##*/}"; }