2

我想使用参数扩展获取给定文件的直接父目录的名称,例如foogiven 。/home/blah/foo/bar.txt现在我可以用两行来做到这一点:

f="/home/blah/foo/bar.txt"
dir_name="${f%/*}"
immediate_parent="${dir_name##*/}"

但我对参数扩展很陌生,所以我认为这可以优化。有没有办法只用一行来做到这一点?

4

1 回答 1

5

您不能使用单个参数扩展来做到这一点,但您可以使用=~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")}
      
于 2015-12-05T18:56:49.183 回答