将路径拆分为文件名

将路径拆分为文件名

在我的 zsh 脚本中,我想知道我的工作目录是否以以下开头/cygdrive/?/...或完全匹配/cygdrive/?(其中驱动器号(?)可以是与字母 c 不同的任何字母),如果是,则检索到两个变量/cygdrive/?部分和剩余的/...。示例:如果我的工作目录是/cygdrive/r/abc/xyz,我希望将变量head设置为/cygdrive/r并将变量tail设置为/abc/xyz。例如,如果 PWD 只是 ,则/cygdrive/r该变量tail应该为空。

我更喜欢仅使用 zsh 内部命令的解决方案,即不需要生成进程。

我想出了以下解决方案,它可以完成工作,但我不喜欢它:

if [[ $PWD == /cygdrive/[abd-z]* ]]
then
  local head=${PWD:0:11}
  local tail=${PWD#/cygdrive/?}
  ....
fi

特别是,我不喜欢 head 的计算,其硬编码值为 11,我想知道是否可能有一种完全不同的方法,这会更优雅。

更新:我知道我的if条件也成立,例如,如果 PWD 是 ,/cygdrive/foo但对于我的应用程序,我不认为这是一个问题。当然,如果你能建议一个更好的替代方案来编写条件,确切地做我想做的事,我感谢任何评论。

答案1

if [[ $PWD =~ '^(/cygdrive/[abd-z])(.*)' ]]; then
  head=$match[1]
  tail=$match[2]
fi

与全局相同:

set -o extendedglob
if [[ $PWD = (#b)(/cygdrive/[abd-z])(*) ]]; then
  head=$match[1]
  tail=$match[2]
fi

zshGlob 还具有使用自身模式匹配的优势,其中d-z仅匹配defghijklmnopqrstuvwxyz,而=~会使用系统的正则表达式,其中[d-z]可能非常匹配更多字符(例如é甚至dzs匈牙利地区中的字符序列)。执行set -o rematchpcre会导致=~使用 PCRE,在这方面这更合理。

不匹配/cygdrive/foo

if [[ $PWD =~ '^(/cygdrive/[abd-z])(/.*)?$' ]]; then
  head=$match[1]
  tail=$match[2]
fi

与球:

set -o extendedglob
if [[ $PWD = (#b)(/cygdrive/[abd-z])(/*|) ]]; then
  head=$match[1]
  tail=$match[2]
fi

答案2

由于您已经知道如何获取变量的后缀,因此可以将其从变量中删除以具有前缀:

if [[ $PWD == /cygdrive/[abd-z] ]]
then
  local tail=${PWD#/cygdrive/?}
  local head=${PWD%%$tail}
  ....
fi

至于条件,可以在Zsh中使用正则表达式:

if [[ $PWD =~ '^/cygdrive/[abd-z](/.*)?$' ]]
then
    tail=${PWD#/cygdrive/?}
    head=${PWD%%$tail}

    echo "head is $head"
    echo "tail is $tail"
else
    echo "no match"
fi

相关内容