我想使用参数扩展获取foo
给定文件的直接父目录的名称,例如给定/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")}