Bu bash kodundaki bu üç şeyi benim için açıklayabilir misiniz?


10

Bir var functionbenim de .bashrcdosyaya. Ne yaptığını biliyorum, X ile birçok dizini arttırıyorcd

İşte burada:

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
}

Ama bu üç şeyi benim için açıklayabilir misin?

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

Neden sadece böyle yapmıyorsunuz:

up()
{
    limit=$1

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

Kullanımı:

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

Yanıtlar:


24
  1. d=$d/..değişkenin /..geçerli içeriğine ekler d. dboş başlar, sonra ilk yineleme yapar /.., ikinci /../..vb.

  2. sed 's/^\///'ilkini düşürür /, böylece /../..olur  ../..(bu bir parametre genişletmesi kullanılarak yapılabilir d=${d#/}).

  3. d=.. sadece durumu bağlamında mantıklı:

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

    Bu d, bu noktada boşsa üst dizine gitmenizi sağlar. ( uphiçbir argüman eşdeğer değildir cd ...)

Bu yaklaşım yinelemeden daha iyidir, cd ..çünkü cd -bir adımda bir önceki dizine (kullanıcının bakış açısından) dönme yeteneğini korur .

İşlev basitleştirilebilir:

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

Bu, en az bir seviye yukarı çıkmak istediğimizi ve n - 1 seviye eklediğimizi varsayar , bu nedenle öncüyü kaldırmamız /veya boş olup olmadığını kontrol etmemiz gerekmez $d.

Athena jot( athena-jotDebian'daki paket) kullanarak:

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

( glenn jackman tarafından önerilen bir varyant temelinde ).


Evet, $OLDPWDçiğnemek aklıma geldi. Ve zsh üzerinde cddirstack kullanmak için ayarlanmış, o da.
muru

Yalnızca döngüde kullanmak yerine atamak $1için bir neden var mı ? limit$1
Nick Matteo

1
@kundor varsayılanın 0 olmasını sağlar ( kabuk aritmetiğine bakınız ). ${1:-1}Glenn varyantında olduğu gibi kullanabiliriz .
Stephen Kitt

@kundor Ayrıca insan tarafından okunabilirlik. İyi adlandırılmış bir değişken , ilk argümanın amaçlanan anlamının veya amacının ne olduğunu , öncelikle işlevin ne yaptığını bilmeden veya onu çıkarmak için kodu anlamayı bitirmeden, işlevi okumaya başladığınızda söyler .
mtraceur

2

Ama bu üç şeyi benim için açıklayabilir misin?

  1. d = $ d / ..

    Bu, var dile ilgili mevcut içerikleri birleştirir /..ve geri atar d.
    Sonuç olarak dtekrarlanan bir dize yapmaktır /../../../...

  2. sed 's / ^ ///'

    İletiyi yerleştirdiğiniz kodda /verilen dizeden d(echo $ d) satır aralığını kaldırın . Ters eğik çizgiyi önlemek için
    muhtemelen daha iyi yazılmıştır sed 's|^/||'.

    Alternatif (daha hızlı ve daha basit) yazmaktır d=${d#/}.

  3. d = ..

    Dizeyi ..var d.
    Bu sadece testin boş olduğunu bildirmesi durumunda den az bir tane olmasını sağlamanın bir yolu olarak anlamlıdır . Ve bu sadece sed komutunun bir karakteri kaldırması nedeniyle olabilir . Karakteri d'den kaldırmaya gerek yoksa, veya öğesine gerek yoktur ...if [ -z "$d" ]; thendd
    sedif


Sorunuzdaki kod her zaman en az bir dizin yukarı taşınır.

Daha iyi

  • local ddeğişkenin boş olduğundan emin olmak için yeterlidir, başka bir şeye gerek yoktur.
    Ancak, yerel sadece bash veya dash gibi bazı kabuklarda çalışır. Özellikle, ksh(as yash) localkomutuna sahip değildir . Daha taşınabilir bir çözüm:

    [ "$KSH_VERSION$YASH_VERSION" ] && typeset c='' d='' i='' || local c='' d='' i=''
  • for((Sözdizimi taşınabilir değildir. Gibi bir şey daha iyi kullanın:

    while [ "$((i+=1))" -lt "$limit" ]; do
  • Güçlü.
    İlk işlev bağımsız değişkenine verilen değerler negatif veya metin olabilirse, işlev bu değerleri işlemek için sağlam olmalıdır.
    İlk olarak, değerleri sadece sayılarla sınırlayalım ( ciçin kullanacağım count):

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

    Ve sonra sayım değerini yalnızca pozitif değerlerle sınırlayın:

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

Bu işlev 0 veya herhangi bir metni mutlulukla kabul eder (hatasız):

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 \İşlevi test ettiğinizde kaldırın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.