更好的

更好的

function我的档案里有一份.bashrc。我知道它的作用,它会增加 X 个目录cd

这里是:

up()
{
    local d=""
    limit=$1
    for ((i=1 ; i <= limit ; i++))
      do
        d=$d/..
      done
    d=$(echo $d | sed 's/^\///')
    if [ -z "$d" ]; then
      d=..
    fi
    cd $d
}

但你能为我解释一下这三件事吗?

  1. d=$d/..
  2. sed 's/^\///'
  3. d=..

为什么不这样做:

up()
{
    limit=$1

    for ((i=1 ; i <= limit ; i++))
    do
        cd ..
    done
}

用法:

<<<>>>~$ up 3
<<<>>>/$

答案1

  1. d=$d/..添加/..到变量的当前内容dd从空开始,然后第一次迭代使其成为/..,第二次迭代/../..等等。

  2. sed 's/^\///'删除第一个/,因此/../..变为 ../..(这可以使用参数扩展 来完成d=${d#/})。

  3. d=..仅在其条件的上下文中才有意义:

    if [ -z "$d" ]; then
      d=..
    fi
    

    这确保了如果d此时为空,您将转到父目录。 (up不带参数相当于cd ..。)

这种方法比迭代更好,cd ..因为它保留了cd -一步返回到上一目录(从用户的角度来看)的能力。

该函数可以简化:

up() {
  local d=..
  for ((i = 1; i < ${1:-1}; i++)); do d=$d/..; done
  cd $d
}

这假设我们想要至少提升一级,并添加n - 1级别,因此我们不需要删除前导/或检查空的$d.

使用 Athena jotathena-jotDebian 中的软件包):

up() { cd $(jot -b .. -s / "${1:-1}"); }

(基于变体建议来自格伦·杰克曼)。

答案2

但你能为我解释一下这三件事吗?

  1. d=$d/..

    这会将 var 的当前内容d与var 连接起来/..并将其分配回d
    最终结果是制作d一个重复的字符串,如/../../../...

  2. sed 's/^///'

    从您发布的代码中/提供的字符串中删除前导(echo $d)。 可能更好地编写以避免反斜杠。 d
    sed 's|^/||'

    另一种选择(更快更简单)是编写d=${d#/}.

  3. d=..

    将字符串分配..给 var d
    这只有作为确保d至少有 ..如果测试if [ -z "$d" ]; then表明 vard为空。这只能发生,因为 sed 命令正在从 中删除一个字符d
    如果不需要从 d 中删除字符,则不需要sedor if


您问题中的代码始终会向上移动至少一个目录。

更好的

  • local d足以确保变量为空,不需要其他任何东西。
    但是,local 只在某些 shell 中有效,例如 bash 或 dash。具体来说,ksh(as yash) 没有local命令。更便携的解决方案是:

    [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
    
  • 语法for((不可移植。最好使用类似的东西:

    while [ "$((i+=1))" -lt "$limit" ]; do
    
  • 强壮的。
    如果赋予函数第一个参数的值可以是负数或文本,则该函数应该能够稳健地处理这些值。
    首先,让我们将值限制为仅数字(我将使用cfor count):

    c=${1%%[!0-9]*}
    

    然后将计数值限制为仅正值:

    let "c = (c>0)?c:0"
    

这个函数很乐意接受 0 或任何文本(没有错误):

up()
{
    [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
    c=${1%%[!0-9]*}
    c=$(((c>0)?c:0))
    while [ "$((i+=1))" -le "$c" ]; do d="$d../"; done
    echo \
        cd "${d%/}"         # Removing the trailing / is not really needed for cd
                            # but it is nice to know it could be done cleanly.
}

up 2
up 0
up asdf

echo \当您测试了该功能后,请删除。

相关内容