您能在这段bash代码中为我解释这三件事吗?


10

我有一个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
<<<>>>/$

Answers:


24
  1. d=$d/..添加/..d变量的当前内容。d从空开始,然后第一次迭代/..,第二次/../..以此类推。

  2. sed 's/^\///'删除first /,因此/../..变为  ../..(可以使用参数扩展来完成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}"); }

(基于glenn jackman建议的变体)。


是的,我$OLDPWD被践踏了。在zsh上cd,它也设置为使用目录栈。
muru

是否有某些原因可以分配$1limit而不是仅$1在循环中使用?
尼克·马特奥

1
@kundor确保默认值为0(请参阅shell算术)。可以${1:-1}像glenn的变体一样使用。
史蒂芬·基特

@kundor也是人类可读性。当您开始阅读该函数时,一个命名良好的变量将告诉您第一个参数的预期含义目的,而不必首先知道该函数的作用或完全理解要推导它的代码。
mtraceur

2

但是您能为我解释这三件事吗?

  1. d = $ d / ..

    这会将var的当前内容与连接在一起d/..并将其分配回给d
    最终结果是使d字符串像一样重复/../../../..

  2. sed's / ^ ///'

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

    另一种方法(更快,更简单)是编写d=${d#/}

  3. d = ..

    将字符串分配..给var d
    这仅是有道理的,以此来保证d至少有一个 ..的情况下,测试if [ -z "$d" ]; then信号,该变种d是空的。这只能发生,因为sed命令正在从中删除一个字符d
    如果不需要从d中删除字符,则不需要sedif


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

更好

  • local d足以确保该变量为空,不需要其他任何操作。
    但是,本地只能在某些外壳中使用,例如bash或dash。具体来说,ksh(如yash)没有local命令。更加便携的解决方案是:

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

    while [ "$((i+=1))" -lt "$limit" ]; do
  • 强大的。
    如果赋予函数第一个参数的值可以是负数或文本,则该函数应具有强大的处理能力。
    首先,让我们将值限制为仅数字(我将c用于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 \测试完功能后,将其删除。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.