我想使用参数扩展获取给定文件的直接父目录的名称,例如foo
given 。/home/blah/foo/bar.txt
现在我可以用两行来做到这一点:
f="/home/blah/foo/bar.txt"
dir_name="${f%/*}"
immediate_parent="${dir_name##*/}"
但我对参数扩展很陌生,所以我认为这可以优化。有没有办法只用一行来做到这一点?
我想使用参数扩展获取给定文件的直接父目录的名称,例如foo
given 。/home/blah/foo/bar.txt
现在我可以用两行来做到这一点:
f="/home/blah/foo/bar.txt"
dir_name="${f%/*}"
immediate_parent="${dir_name##*/}"
但我对参数扩展很陌生,所以我认为这可以优化。有没有办法只用一行来做到这一点?
您不能使用单个参数扩展来做到这一点,但您可以使用=~
Bash 的正则表达式匹配运算符:
[[ $f =~ ^.*/(.+)/.+$ ]] && immediate_parent=${BASH_REMATCH[1]}
注意:假设绝对路径至少包含 2 个组件。
如果可以接受调用外部实用程序,请awk
提供一个可能更简单的替代方案:
immediate_parent=$(awk -F/ '{ print $(NF-1) }' <<<"$f")
至于为什么不能单参数展开:
参数扩展允许从变量值中去除前缀 ( / )或后缀( / ) ,但不能同时去除两者。#
##
%
%%
使用单参数展开,只能通过字符位置和长度来提取内部子串;例如,基于样本输入的硬编码解决方案将是:immediate_parent=${f:11:3}
您可以使用算术表达式甚至命令替换作为参数扩展参数,但是如果我们尝试一下,这种方法的毫无意义——至少在这种情况下——会变得很明显;注意嵌入的命令替换 - 第一个计算字符位置,第二个计算长度:
immediate_parent=${f:$(d=${f%/*/*}; printf %s ${#d})+1:$(awk -F/ '{ print length($(NF-1)) }' <<<"$f")}